2

私はJFreeChartを使用して、いくつかの時系列グラフをプロットしています。正常に動作しているように見えましたが、今日の時点では、すべてのグラフがちらつき、ランダムにグリッチが発生しているため、グラフを見ることができません。最小化して最大化すると、次の更新またはマウスクリックまで数秒間問題が修正されます。誰かが問題が何であるかについての考えを持っていますか?

代替テキスト

コードは非常に単純です。

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;
}
4

2 に答える 2

1

一貫性のない/破損したイメージが表示される場合は、イベントディスパッチスレッド以外のスレッドでデータセットを更新していることを示している場合があります。これを確認するために、いくつかのassertステートメントを追加することをお勧めします。

SwingUtilities.isEventDispatchThread();をアサートします。

また、JFreeChartは、新しいデータポイントが追加されるたびにグラフ全体を再レンダリングするため、特に効率的ではないことに注意してください。ここで行うことができる最適化の1つは次のとおりです。

  • アプリが複数のグラフで構成されている場合は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.
    }
  }
}
于 2009-10-13T13:28:30.873 に答える
0

グラフにデータポイントをどのように追加していますか?AWTイベントディスパッチスレッドでそれを行っていますか?おそらくSwingUtilities.invokeAndWaitを使用する必要があります。invokeLaterを使用できますが、プログラムが他のことを行うのに忙しい場合、GUIがすぐに更新されない可能性があります。

Also, how many data points do you have? I discovered that the code for fixed auto-range was quite inefficient for large numbers of data points. That may have been fixed in the most recent version (I don't know).

于 2009-10-13T13:24:49.360 に答える