Wololo
Wololo

Reputation: 861

There is some space at the end of the bar chart I've created using Graphics

I am trying to make a bar chart. Everything goes fine; the code compiles and runs successfully. But the frame (window) is not packed perfectly. There is some space at the end of the bar chart. I just want this space removed.

public class BarChart extends JPanel{   
    int[] percentage;
    Color color;
    double barOffset;

    public BarChart(int[] percentage, Color color) {        
        this.color = color;
        this.percentage = percentage;   
    }

    public BarChart(int[] percentage) { 
        this.color = Color.black;
        this.percentage = percentage;       
    }

    public BarChart() {     
        this.color = Color.black;

    }

    int w = 1,h = 1;

    protected void paintComponent(Graphics g) {     
        super.paintComponent(g);

        w = getWidth();
        h = getHeight();
        g.setColor(color);
        barOffset = w*0.05;
        int barWidth = (int)(w*0.1);

        for(int i = 0; i<percentage.length; i++) {
            g.fillRect((int)(barOffset),(int)(h*0.95-2*percentage[i]), barWidth, 2*percentage[i]);

            if(i < percentage.length-1)
                barOffset = (i+2)*w*0.05 + (i+1)*(barWidth);
        }                       
    }
}

Upvotes: 1

Views: 82

Answers (1)

Parker
Parker

Reputation: 7519

This was not a packing error, but rather you were drawing off the edge of the component. To check for packing errors, set a background color for the container that is distinct from the component color.

For the set int[] p = new int[]{100, 5, 6, 9, 1, 0, 5, 100};, your bars are being drawn as follows:

component dimensions: width=104 height=10
bar[0]: xLeft=5 yTop=-190 barWidth=10 barHeight=200
bar[1]: xLeft=20 yTop=0 barWidth=10 barHeight=10
bar[2]: xLeft=35 yTop=-2 barWidth=10 barHeight=12
bar[3]: xLeft=50 yTop=-8 barWidth=10 barHeight=18
bar[4]: xLeft=66 yTop=7 barWidth=10 barHeight=2
bar[5]: xLeft=81 yTop=9 barWidth=10 barHeight=0
bar[6]: xLeft=96 yTop=0 barWidth=10 barHeight=10
bar[7]: xLeft=111 yTop=-190 barWidth=10 barHeight=200

I think this produces what you're looking for. Drawing components can be tricky, and the way I mitigate the complexity is to keep track of my screen locations semantically.

import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class BarChart extends JPanel
{
    public static void main(String[] args)
    {
        int[] p = new int[]{100, 5, 6, 9, 1, 0, 5, 100};
        JFrame f = new JFrame();
        f.setBackground(Color.BLUE);
        BarChart chart = new BarChart(p);
        chart.setBackground(Color.RED);
        f.add(chart);
        f.pack();
        f.show();
    }

    private int[] percentage;
    private Color color;
    private boolean padEnds = true;

    public BarChart(int[] percentage, Color color)
    {
        this.percentage = percentage;
        this.color = color;
        return;
    }

    public BarChart(int[] percentage)
    {
        this(percentage, Color.BLACK);
        return;
    }

    public BarChart()
    {
        this(new int[0]);
        return;
    }

    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);

        g.setColor(this.color);

        int width = super.getWidth();
        int height = super.getHeight();
        int topPadding = Math.round(height * 0.05f);

        int barCount = this.percentage.length;

        int barOffset = Math.round(width * 0.025f); // 2.5% (in pixels) reserved space on both sides of each bar == 5% between bars
        int totalOffsetWidth = (barOffset * 2) * barCount;

        if (!this.padEnds)
        {
            totalOffsetWidth -= (barOffset * 2);
        }

        int availableWidth = width - totalOffsetWidth;
        int availableHeight = height - topPadding;

        int barWidth = (int) Math.floor((float) availableWidth / (float) barCount);

        int xLeft = 0;

        for (int i = 0; i < barCount; i++)
        {
            int percent = this.percentage[i];

            if (this.padEnds || (i != 0))
            {
                xLeft += barOffset; // Add offset here to pad left side of each bar.
            }

            int barHeight = Math.round(((float) availableHeight) * ((float) percent / 100f));

            int yTop = topPadding + (availableHeight - barHeight);

            g.fillRect(xLeft, yTop, barWidth, barHeight);

            xLeft += barWidth; // advance the next drawing position

            if (this.padEnds || (i != (barCount - 1)))
            {
                xLeft += barOffset; // Add offset here to pad right side of each bar.
            }
        }

        return;
    }
}

Upvotes: 3

Related Questions