Glitchy графики с использованием JFreeChart - PullRequest
2 голосов
/ 13 октября 2009

Я работаю с JFreeChart для построения нескольких диаграмм TimeSeries. Казалось, что он работает нормально, но на сегодняшний день все графики, кажется, мерцают и случайным образом сбиваются, делая их невидимыми. Если я сверну и разверну, проблема будет решена за несколько секунд до следующего обновления или щелчка мышью. У кого-нибудь есть представление о том, в чем может быть проблема?

alt text

Код довольно прост:

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

Ответы [ 2 ]

1 голос
/ 13 октября 2009

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

assert SwingUtilities.isEventDispatchThread ();

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

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

EDIT

Исходя из вашего комментария к ответу Дэна, звучит так, что ваш поток ввода-вывода, получающий сообщения, также обновляет набор данных 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.
    }
  }
}
0 голосов
/ 13 октября 2009

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

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

...