0

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.

camickr
  • 321,443
  • 19
  • 166
  • 288
Ryan
  • 60
  • 7
  • 3
    Each Swing component is responsible for determining its own preferred size. When doing custom painting you need to override the getPreferredSize() method of your class. The scrollbars will appear in the JScrollPane when the preferred size of the panel is greater than the size of the scroll panel. – camickr Apr 08 '21 at 19:21
  • 2
    This [Stack Overflow answer](https://stackoverflow.com/questions/66263438/paintcomponent-not-called-when-i-scroll-both-horizontal-and-vertical-scrollbars/66267763#66267763) shows one way. – Gilbert Le Blanc Apr 08 '21 at 20:07

0 Answers0