【问题标题】:How to update dataset in JFreeChart Bar Chart如何更新 JFreeChart 条形图中的数据集
【发布时间】:2018-05-05 01:01:15
【问题描述】:

我有一个JFrame,在这个框架中有一个JPanel,在一个JPanel中有一个JFreeChart(图表从方法中获取数据集),这个图表被添加到在JPanel中创建的ChartPanel,然后ChartPanel被添加到JPanel。此外,我在 JPanel 中有 JComboBox,如果我更改该 JComboBox 中的选项,则 ActionListener 会更新数据集的值。同样返回数据集的方法,从 JComboBox 中获取一个字符串(数据集的数据取决于 JComboBox 输出)。因此,如果我更改 JComboBox 中的选项,我想用新数据集更新 JFreeChart 并将其显示在屏幕上。我知道我需要在那个 ActionListener 中添加代码,但我不应该在那里添加什么,是否有任何方法可以更新已经创建的 JFreeChart?

private class PanelChart extends JPanel { {
    this.setLayout(new BorderLayout());

    // Create Dataset
    //method GUIImplementation.GetDataForChart takes as an input value of combobox

    CategoryDataset dataset = GUIImplementation.GetDataForChart(comboBoxCrimeTypeChart.getSelectedItem().toString());


    //Create chart
    JFreeChart crimeNumberBarChart = ChartFactory.createBarChart(
        "Number of crimes by type", //Chart Title
        "Fallen within", // Category axis
        "Number of crimes", // Value axis
        dataset,
        PlotOrientation.VERTICAL,
        true,true,false
        );
    ChartPanel panelCrimeNumberBarChart = new ChartPanel(crimeNumberBarChart);
    this.add(panelCrimeNumberBarChart, BorderLayout.CENTER);

    PanelChartSouth panelChartSouth = new PanelChartSouth(); //there is a combobox
    this.add(panelChartSouth, BorderLayout.SOUTH);
}}

private class ChartButtonListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == backChart) {
            SizeAndTitleSetter(0);
            SwapPanelChart(0);
        } else if(e.getSource() == comboBoxCrimeTypeChart) { //comboBoxCrimeTypeChart is a JComboBox from PanelChartSouth
            String crimeType = comboBoxCrimeTypeChart.getSelectedItem().toString();
            System.out.println(crimeType);
            dataset = GUIImplementation.GetDataForChart(crimeType); // dataset updated
        }
    }
}

到目前为止,我只是通过从 JFrame 中删除 PanelChart 然后创建新的 PanelChart 并将其添加到 JFrame 并使用重新绘制和重新验证来设法以某种方式更新该图表。如果我在 JComboBox 中更改了一次选项,它会起作用,在第二次更改后一切都开始在屏幕上停止,旧图表不想消失并且新图表在它下面,如果我调整屏幕大小我可以看到它。

【问题讨论】:

    标签: java swing jfreechart


    【解决方案1】:

    您可以更新现有图表的数据集,如这些examples 所示;当您更新模型(数据集)时,监听图(视图)将相应地更新自己; CategoryDataset 的具体实现通常会提供合适的修改器。

    DefaultCategoryDataset model = …
    …
    @Override
    public void actionPerformed(ActionEvent e) {
        model.setValue(…);
    }
    

    您可以使用相关绘图的setDataset() 方法替换现有图表的数据集。

    CategoryPlot plot = (CategoryPlot) chart.getPlot();
    …
    @Override
    public void actionPerformed(ActionEvent e) {
        plot.setDataset(…);
    }
    

    虽然按照 here 的建议替换封闭视图组件在技术上是可行的,但通常最好按照 here 的建议更新或替换模型。

    【讨论】:

    • method .setValue for CategoryDataset 不存在,但 CategoryPlot 选项效果很好,非常感谢我在 Internet 上找不到它!这比我的答案好得多。
    • @sebaoka:对,我应该指定CategoryDataset的具体实现;已编辑。
    【解决方案2】:

    我找到了一个可行的答案,但它有一个小问题。所以我的 ActionListener 现在看起来像这样:

    private class ChartButtonListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            if(e.getSource() == backChart) {
                SizeAndTitleSetter(0);
                SwapPanelChart(0);
            } else if(e.getSource() == comboBoxCrimeTypeChart) {
                SwingUtilities.invokeLater(() -> {
                    frame.remove(panelChart);
                    panelChart = new PanelChart();
                    frame.add(panelChart);
                    frame.pack();
                    frame.invalidate();
                    frame.revalidate();
                    frame.repaint();
                });
            }
        }
    }
    

    在我添加 SwingUtilities.invokeLater 后,它开始运行良好,但现在的问题是在更改 JComboBox 选项几次后程序变慢了。电脑迷们快疯了,现在我不知道这是这部分代码的问题还是我在某个地方出错了。当我返回程序的主菜单并使用其他组件时,它的工作与以前相同。

    我发现了为什么它开始变得迟钝,在一个类 PanelChartSouth 中,我将 actionListener 添加到 JComboBox,并且在每次删除和创建新的 PanelChart 之后,下一个 actionListener 被添加到 JComboBox。所以防止它我已经将添加动作侦听器的操作添加到 if 语句中

          if(ifActionListenerSet == false) {
    
            ifActionListenerSet = true;
        ChartButtonListener chartButtonListener = new ChartButtonListener();
        backChart.addActionListener(chartButtonListener);
        comboBoxCrimeTypeChart.addActionListener(chartButtonListener);
        }
    

    现在一切都很好。

    【讨论】:

    • 这可行,但我会推荐@trashgod 的答案。
    猜你喜欢
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多