1

I'm having issues with refreshing/repainting a BarChart after setting a zero value of a CategoryDataset to a very large number.

private class Test
    extends ApplicationFrame {

    private DefaultCategoryDataset set;

    public Test(
        String newTitle) {
        super(newTitle);
        set = new DefaultCategoryDataset();
        set.addValue(0, "Test", "1");
        JFreeChart barChart = ChartFactory.createBarChart(
                "Test",
                "Category",
                "Score",
                set,
                PlotOrientation.VERTICAL,
                true,
                true,
                false);

        JPanel mainPanel = new JPanel(new GridLayout());

        ChartPanel chartPanel = new ChartPanel(barChart);
        chartPanel.setPreferredSize(new java.awt.Dimension(560, 367));
        mainPanel.add(chartPanel);

        JButton b = new JButton();

        createDataset();
        b.addActionListener(e -> {
            set.setValue(Integer.MAX_VALUE, "Test", "1");
        });
        mainPanel.add(b);
        setContentPane(mainPanel);
        pack();
        setVisible(true);
    }

Here is the chart with a zero value.

enter image description here

Setting the value to a very large number.

enter image description here

Clicking inside the chart.

enter image description here

How can the chart be properly refreshed? I've tried to repaint the ChartPanel, but it hasn't worked.

Ubuntix
  • 324
  • 4
  • 15

1 Answers1

1

Be sure to construct and manipulate Swing GUI objects only on the event dispatch thread. In addition, override getPreferredSize(), as shown here, to establish the chart's initial size. In the variation below, note how repeated clicks on the Clear, Zero and Update buttons leave the chart itself unchanged, while updating the dataset, plot, range axis and legend.

image

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.DefaultCategoryDataset;

/**
 * @see https://stackoverflow.com/q/50854965/230513
 */
public class Test {

    private final DefaultCategoryDataset set = new DefaultCategoryDataset();
    private int i;

    private void display() {
        JFrame f = new JFrame("Test");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        set.addValue(0, "Test", "1");
        JFreeChart barChart = ChartFactory.createBarChart(
            "Test", "Category", "Score", set,
            PlotOrientation.VERTICAL, true, true, false);

        JPanel mainPanel = new JPanel(new BorderLayout());
        mainPanel.add(new ChartPanel(barChart) {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(567, 345);
            }
        });
        JPanel p = new JPanel();
        p.add(new JButton(new AbstractAction("Clear") {

            @Override
            public void actionPerformed(ActionEvent e) {
                set.clear();
                i = 0;
            }
        }));
        p.add(new JButton(new AbstractAction("Zero") {

            @Override
            public void actionPerformed(ActionEvent e) {
                set.setValue(0, "Test", "1");
                i = 0;
            }
        }));
        p.add(new JButton(new AbstractAction("Update") {

            @Override
            public void actionPerformed(ActionEvent e) {
                set.setValue(i += 10, "Test", "1");
            }
        }));
        mainPanel.add(p, BorderLayout.SOUTH);
        f.add(mainPanel);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Test()::display);
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Thank you for your answer, Apperently, this does not solve my problem. Change your "Update" mechanism to a larger integer, e.g. Integer.MAX_VALUE instead of adding a small number like 10. The problem only appears if updating a zero value to a very large number. – Ubuntix Jun 18 '18 at 07:24
  • I see integer overflow but no anomaly if I initialize the `DefaultCategoryDataset` explicitly at the outset. – trashgod Jun 18 '18 at 18:06
  • The integer overflow, of course, happens if you add Integer.MAX_VALUE twice. So, here are the steps to reproduce: 1. Start Application 2. "update" -> Result: Y-Axis is shifted to the left, one cannot read the tick-labels. You can set it back to zero (using your "zero"-button, not the "clear"-button) and update again -> same thing happens. – Ubuntix Jun 20 '18 at 10:13
  • I see it, now; I don't know why it happens; `set.addValue(1, "Test", "1")` in `display()` may suggest a workaround for your use case. – trashgod Jun 20 '18 at 16:44