Reputation: 861
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
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