Glitchy графики с использованием JFreeChart

Я работаю с 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;
}
13.10.2009 12:41:34
Почему вы отмечаете XYPlot как окончательный?
Koekiebox 13.10.2009 13:22:31
Хм, это просто пережиток попытки попробовать разные решения в интернете, чтобы попытаться решить проблему. Удаление не имеет значения.
thodinc 13.10.2009 13:54:05
2 ОТВЕТА

Как вы добавляете точки данных на график? Вы делаете это в потоке рассылки событий AWT? Вы, вероятно, должны использовать SwingUtilities.invokeAndWait . Вы можете использовать invokeLater, но если ваша программа занята другими делами, графический интерфейс может не обновляться быстро.

Кроме того, сколько точек данных у вас есть? Я обнаружил, что код для фиксированного автоматического диапазона был неэффективен для большого количества точек данных. Возможно, это было исправлено в самой последней версии (я не знаю).

0
23.05.2017 12:33:39
Ну, у меня есть отдельный поток, который получает сообщения от другого узла и добавляет к серии двойное значение: ts.addOrUpdate (new Millisecond (), Update); В одном случае новая точка данных появляется каждые 10 секунд, тогда как в другом - до 5 раз в секунду. Однако оба, похоже, испытывают одну и ту же проблему.
thodinc 13.10.2009 13:39:39
Кроме того, в случае обновлений с интервалами 10 с первая точка данных не отображается, пока не прибудет вторая, а затем обе точки будут видны.
thodinc 13.10.2009 13:43:04
Поток, получающий сообщения, должен маршалировать обновление временного ряда в поток диспетчеризации событий. Я предлагаю использовать SwingUtilities.invokeLater, чтобы предотвратить блокировку потока ввода-вывода во время обновления пользовательского интерфейса.
Adamski 13.10.2009 13:50:27
Я не уверен, в чем проблема именно потому, что я только что запустил программу на другом компьютере, и это казалось нормальным. Может быть, библиотека повреждена?
thodinc 22.10.2009 10:19:17
Проблема исправлена! Кажется, был конфликт с моим графическим драйвером. Я добавил следующий флаг, и проблем пока нет: -Dsun.java2d.opengl = true
thodinc 22.10.2009 10:29:03

Если вы видите несогласованное / поврежденное изображение, это иногда указывает на обновление набора данных в потоке, отличном от потока отправки событий. Я предлагаю вам добавить несколько утверждений assert, чтобы проверить это:

assert SwingUtilities.isEventDispatchThread ();

Также обратите внимание, что JFreeChart не особенно эффективен, так как он перерисовывает весь график всякий раз, когда добавляется новая точка данных. Одна оптимизация, которую вы могли бы сделать здесь:

  • Если ваше приложение состоит из нескольких диаграмм, то распространяется только DatasetChangeEventна диаграмму, отображаемую в данный момент. Если диаграмма скрыта (например, на другой вкладке), просто запишите тот факт, что она устарела и ее необходимо повторно отобразить при выборе вкладки.

РЕДАКТИРОВАТЬ

Исходя из вашего комментария к ответу Дэна, звучит так, что ваш поток ввода-вывода, получающий сообщения, также обновляет набор данных JFreeChart, хотя на самом деле обновление должно выполняться в потоке диспетчеризации событий (а сообщения должны выполняться в отдельном потоке ввода-вывода). ). Чтобы достичь этого, я предлагаю вам использовать подход, основанный на дросселе, при котором события ввода-вывода объединяются в группы. Вы можете использовать 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.
    }
  }
}
1
13.10.2009 13:56:10
Я поставил assert SwingUtilities.isEventDispatchThread (); прямо над точкой, где набор данных обновляется после получения сообщения, и это, похоже, не имеет никакого значения. Кроме того, кажется, что если я нажму на график (без перетаскивания или что-либо), проблема станет хуже. i18.photobucket.com/albums/b115/thodinc/jfreebug.jpg
thodinc 13.10.2009 13:49:44
Прямо сейчас я просто открываю новый JFrame для отображения графиков, но идея с вкладками тоже звучит хорошо. Однако проблема возникает, даже если открыт только один граф. Раньше такого не происходило, а происходит сейчас, даже если я перейду к более старой версии кода.
thodinc 13.10.2009 13:52:11
Хотя ваша реализация обработки сообщений намного эффективнее, чем то, что я сделал, похоже, она не влияет на графическую часть. Я использовал LinkedBlockingQueue с invokeLater и все еще получаю поврежденные графики.
thodinc 13.10.2009 15:49:45