我正在使用 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;
}
最佳答案
如果您看到不一致/损坏的图像,有时表明在事件调度线程以外的线程上更新了数据集。我建议您添加一些断言语句来验证这一点:
断言 SwingUtilities.isEventDispatchThread();
另外,请注意 JFreeChart 并不是特别有效,因为它会在添加新数据点时重新呈现整个图形。您可以在此处进行的一项优化是:
- 如果您的应用包含多个图表,则只传播当前显示的图表的
DatasetChangeEvent
。如果图表被隐藏(例如在不同的选项卡上),则只需记录它已过时并且需要在选择选项卡时重新呈现的事实。
编辑
根据您对 Dan 回复的评论,听起来您的 I/O 线程接收消息也在更新 JFreeChart 数据集,而实际上更新应该在事件调度线程上执行(并且消息应该在单独的 I 上执行/O 线程)。为实现这一点,我建议您使用基于限制的方法,将 I/O 事件集中在一起。您可以使用 BlockingQueue
来实现此目的;例如
// 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.
}
}
}
关于java - 使用 JFreeChart 的故障绘图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1559958/