I have a piece of code that creates a Frequency Table Bar Chart ChartPanel(String chartTitle, ArrayList<String> chartValues, ArrayList<Integer> chartValuesFrequency)
.
The code currently displays all the data onto the current viewport size. I've tried to set the bar width to a fixes size of 300 however the bar chart goes off the panel. I had then decided to add it onto a JScrollPane and setting the preferred size to a width of around 3000. However This is really inefficient as the number of chartValues could change.
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
public class ChartPanel extends JPanel {
private final String title;
private final ArrayList<String> values;
private final ArrayList<Integer> frequency;
private int clientWidth;
public ChartPanel(String chartTitle, ArrayList<String> chartValues, ArrayList<Integer> chartValuesFrequency) {
this.title = chartTitle;
this.values = chartValues;
this.frequency = chartValuesFrequency;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (frequency == null || frequency.size() == 0)
return;
int minValue = 0;
int maxValue = 0;
for (Integer integer : frequency) {
if (minValue > integer)
minValue = integer;
if (maxValue < integer)
maxValue = integer;
}
Dimension d = getSize();
clientWidth = d.width;
int clientHeight = d.height;
int barWidth = 300;
Font titleFont = new Font("SansSerif", Font.BOLD, 20);
FontMetrics titleFontMetrics = g.getFontMetrics(titleFont);
Font labelFont = new Font("SansSerif", Font.PLAIN, 10);
FontMetrics labelFontMetrics = g.getFontMetrics(labelFont);
int titleWidth = titleFontMetrics.stringWidth(title);
int y = titleFontMetrics.getAscent();
int x = (clientWidth - titleWidth) / 2;
g.setFont(titleFont);
g.drawString(title, x, y);
int top = titleFontMetrics.getHeight();
int bottom = labelFontMetrics.getHeight();
if (maxValue == minValue)
return;
int scale = (clientHeight - top - bottom) / (maxValue - minValue);
y = clientHeight - labelFontMetrics.getDescent();
g.setFont(labelFont);
for (int i = 0; i < frequency.size(); i++) {
int valueX = i * barWidth + 1;
int valueY = top;
int height = frequency.get(i)* scale;
if (frequency.get(i) >= 0)
valueY += (maxValue - frequency.get(i)) * scale;
else {
valueY += maxValue * scale;
height = -height;
}
g.setColor(Color.LIGHT_GRAY);
g.fillRect(valueX, valueY, barWidth - 2, height);
g.setColor(Color.black);
g.drawRect(valueX, valueY, barWidth - 2, height);
String label = values.get(i);
if (label.equals("")){
int labelWidth = labelFontMetrics.stringWidth(values.get(i));
x = i * barWidth + (barWidth - labelWidth) / 2;
g.drawString("Null Value", x, y);
}else{
int labelWidth = labelFontMetrics.stringWidth(values.get(i));
x = i * barWidth + (barWidth - labelWidth) / 2;
g.drawString(values.get(i), x, y);
}
}
}
}
Any help is greatly appreciated.