我正在使用JFreeChart绘制几个TimeSeries图表。它看起来工作正常,但截至今天,所有图形似乎都闪烁,并且随机出现故障,使它们无法看到。如果我最小化并最大化,问题将得到修复几秒钟,直到下一次更新或鼠标单击。有没有人知道这个问题是什么?
代码非常简单:
TimeSeries ts = new TimeSeries("Graph", Millisecond.class);
TimeSeriesCollection dataset = new TimeSeriesCollection(ts);
JFreeChart Graph = createChart(dataset);
ChartPanel panel_Graph = new ChartPanel(Graph);
....
JFrame newWindow = new JFrame("Graph");
newWindow.setLayout(new GridLayout());
newWindow.setContentPane(panel_Graph);
newWindow.setMinimumSize(new Dimension(600, 480));
newWindow.setLocationRelativeTo(null);
newWindow.setVisible(true);
static private JFreeChart createChart(TimeSeriesCollection dataset) {
JFreeChart chart = ChartFactory.createTimeSeriesChart(
"Graph",
"Time",
"Value",
dataset,
false,
true,
false
);
final XYPlot plot = chart.getXYPlot();
ValueAxis timeaxis = plot.getDomainAxis();
timeaxis.setAutoRange(true);
timeaxis.setFixedAutoRange(60000.0);
return chart;
}
答案 0 :(得分:1)
如果您看到不一致/损坏的图像,则有时表示在事件调度线程以外的线程上更新数据集。我建议你添加一些断言语句来验证这一点:
断言SwingUtilities.isEventDispatchThread();
另外,请注意JFreeChart不是特别有效,因为每当添加新数据点时它都会重新呈现整个图形。您可以在此处进行的一项优化是:
DatasetChangeEvent
个。如果图表被隐藏(例如,在不同的选项卡上),那么只需记录它是陈旧的,并且在选择选项卡时需要重新呈现。修改强>
根据您对Dan的回复的评论,听起来您的I / O线程接收消息也在更新JFreeChart数据集,而实际上应该在事件调度线程上执行更新(并且消息应该在单独的I上执行/ O线程)。为了达到这个目的,我建议你使用基于节流的方法,将I / O事件放在一起。您可以使用BlockingQueue
来实现此目的; e.g。
// Message definition containing update information.
public interface Message { ... }
// BlockingQueue implementation used to enqueue updates received on I/O thread.
BlockingQueue<Message> msgQ = ...
// Method called by I/O thread when a new Message is received.
public void msgReceived(Message msg) {
boolean wasEmpty = msgQ.isEmpty();
msgQ.add(msg);
// Queue was empty so need to re-invoke Swing thread to process queue.
if (wasEmpty) {
// processUpdates is a re-useable Runnable defined below.
SwingUtilities.invokeLater(processUpdates);
}
}
// Runnable that processes all enqueued events. Much more efficient than:
// a) Creating a new Runnable each time.
// b) Processing one Message per call to run().
private final Runnable processUpdates = new Runnable() {
public void run() {
Message msg;
while ((msg = msgQ.poll) != null) {
// Add msg to dataset within Event Dispatch thread.
}
}
}
答案 1 :(得分:0)
您如何向图表添加数据点?你是在AWT事件派遣线程上做的吗?您应该使用SwingUtilities.invokeAndWait。您可以使用invokeLater,但如果您的程序忙于执行其他操作,则GUI可能不会立即更新。
此外,您有多少数据点?我discovered认为固定自动范围的代码对于大量数据点来说效率很低。这可能已在最新版本中修复(我不知道)。