我有一个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并使用repaint和revalidate来设法更新该图表。如果我在JComboBox中更改了一次选项,在第二次更改之后一切都开始在屏幕上制动,旧图表不想消失并且新图表在其下面,我可以看到它,如果我调整屏幕大小。
答案 0 :(得分:2)
您可以更新现有图表的数据集,如examples所示;当您更新模型(数据集)时,监听图(视图)将相应地更新自身; CategoryDataset
的具体实现通常提供合适的mutator。
DefaultCategoryDataset model = …
…
@Override
public void actionPerformed(ActionEvent e) {
model.setValue(…);
}
您可以使用相关的情节setDataset()
方法替换现有图表的数据集。
CategoryPlot plot = (CategoryPlot) chart.getPlot();
…
@Override
public void actionPerformed(ActionEvent e) {
plot.setDataset(…);
}
答案 1 :(得分:1)
我发现了它的工作答案,但它有一个小问题。所以我的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);
}
现在一切都很好。