Search code examples
javaswingpaintcomponent

Java Swing, I am using a for loop in draw but only the last element is rendered on panel


Edited as an MRE. I wasn't really sure how to write the code without extending JFrame or JPanel. This will reproduce the same error I am seeing. I am trying to render bars on the JPanel, but it seems that only the last iteration of the for loop in the PlotPanel class is being drawn.

package com.company;
import java.awt.*;
import javax.swing.*;

public class VisualizeAlgorithms {
    public static int initPosX = 0;
    public static int initPosY = 0;
    public static int numBars = 200;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            PlotFrame frame = new PlotFrame();

        });
    }
}

class PlotFrame extends JFrame {
    PlotPanel plotPanel;
    PlotFrame() {
        plotPanel = new PlotPanel();
        this.add(plotPanel);
        this.setTitle("Plot");
        this.setBackground(Color.DARK_GRAY);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.pack();
        this.setVisible(true);
        this.setResizable(false);
        this.setLocationRelativeTo(null);
    }

    public int[] createArray(int numBars) {
        int[] numsArray = new int[numBars];
        for (int i = 0; i < numBars; i++) {
            numsArray[i] = i + 1;
        }
        return numsArray;
    }

}

class PlotPanel extends JPanel{

    static final int PLOT_WIDTH = 1200;
    static final int PLOT_HEIGHT = 800;
    static final int MAX_BAR_HEIGHT = PLOT_HEIGHT;
    static final int BAR_WIDTH = PLOT_WIDTH / VisualizeAlgorithms.numBars;

    Dimension plotSize = new Dimension(PLOT_WIDTH, PLOT_HEIGHT);

    PlotPanel() {
        this.setPreferredSize(plotSize);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.CYAN);
        draw(g);
    }

    public void draw(Graphics g){
        int numBars = VisualizeAlgorithms.numBars;
        for (int i = 0; i < numBars; i++) {
            g.fillRect(BAR_WIDTH * i, VisualizeAlgorithms.initPosY, BAR_WIDTH, ((i+1)/numBars)*(MAX_BAR_HEIGHT));
        }
    }
}


Solution

  • Not sure if I can accept comments as answers, so I posted the answer here. It was indeed changing the rectangle height to int h = ((i+1)*MAX_BAR_HEIGHT/numBars). Thanks both to @AndrewThompson and @c0der not only for the answer but the additional information as well.

    Aside: @c0der gave great advice re "when in doubt, print out". I recommend using this change:

    public void draw(Graphics g){
         int numBars = VisualizeAlgorithms.numBars;
         for (int i = 0; i < numBars; i++) {
             int x = BAR_WIDTH * I;
             int y = VisualizeAlgorithms.initPosY;
             int w = BAR_WIDTH;
             int h = ((i+1)/numBars)*(MAX_BAR_HEIGHT);
             System.out.println(String.format("x,y WxH: %1s,%1s %1sx%1s", x,y,w,h));
             g.fillRect(x,y,w,h);
         }
     } 
    

    (print the values used for fillRect)