Вопрос-ответ

Using JFreeChart to display recent changes in a time series

Использование JFreeChart для отображения последних изменений во временном ряду

Как я могу использовать JFreeChart для отображения только самых последних данных в постоянно обновляющемся временном ряду?

Дополнения: Здесь показан полный рабочий пример, включающий принятый ответ. Смотрите также этот вариант, состоящий из двух рядов. Смотрите также этот Вопрос-ответ относительно setTimeBase().

Переведено автоматически
Ответ 1

JFreeChart Класс DynamicTimeSeriesCollection - хороший выбор.

Дополнение: Как отметил @Bahadır, последняя точка ряда постоянно была равна нулю. @Don услужливо предлагает увеличить время и затем добавить данные.

dataset.advanceTime();
dataset.appendData(newData);

введите описание изображения здесь

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.Timer;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.time.DynamicTimeSeriesCollection;
import org.jfree.data.time.Second;
import org.jfree.data.xy.XYDataset;
import org.jfree.chart.ui.ApplicationFrame;
import org.jfree.chart.ui.UIUtils;

/**
* @see http://javalang.ru/a/15521956/230513
* @see http://javalang.ru/questions/5048852
*/

public class DTSCTest extends ApplicationFrame {

private static final String TITLE = "Dynamic Series";
private static final String START = "Start";
private static final String STOP = "Stop";
private static final float MINMAX = 100;
private static final int COUNT = 2 * 60;
private static final int FAST = 100;
private static final int SLOW = FAST * 5;
private static final Random random = new Random();
private Timer timer;

public DTSCTest(final String title) {
super(title);
final DynamicTimeSeriesCollection dataset =
new DynamicTimeSeriesCollection(1, COUNT, new Second());
dataset.setTimeBase(new Second(0, 0, 0, 1, 1, 2011));
dataset.addSeries(gaussianData(), 0, "Gaussian data");
JFreeChart chart = createChart(dataset);

final JButton run = new JButton(STOP);
run.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
if (STOP.equals(cmd)) {
timer.stop();
run.setText(START);
} else {
timer.start();
run.setText(STOP);
}
}
});

final JComboBox combo = new JComboBox();
combo.addItem("Fast");
combo.addItem("Slow");
combo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if ("Fast".equals(combo.getSelectedItem())) {
timer.setDelay(FAST);
} else {
timer.setDelay(SLOW);
}
}
});

this.add(new ChartPanel(chart) {
@Override
public Dimension getPreferredSize() {
return new Dimension(640, 480);
}
}, BorderLayout.CENTER);
JPanel btnPanel = new JPanel(new FlowLayout());
btnPanel.add(run);
btnPanel.add(combo);
this.add(btnPanel, BorderLayout.SOUTH);

timer = new Timer(FAST, new ActionListener() {
float[] newData = new float[1];

@Override
public void actionPerformed(ActionEvent e) {
newData[0] = randomValue();
dataset.advanceTime();
dataset.appendData(newData);
}
});
}

private float randomValue() {
return (float) (random.nextGaussian() * MINMAX / 3);
}

private float[] gaussianData() {
float[] a = new float[COUNT];
for (int i = 0; i < a.length; i++) {
a[i] = randomValue();
}
return a;
}

private JFreeChart createChart(final XYDataset dataset) {
final JFreeChart result = ChartFactory.createTimeSeriesChart(
TITLE, "hh:mm:ss", "milliVolts", dataset, true, true, false);
final XYPlot plot = result.getXYPlot();
ValueAxis domain = plot.getDomainAxis();
domain.setAutoRange(true);
ValueAxis range = plot.getRangeAxis();
range.setRange(-MINMAX, MINMAX);
return result;
}

public void start() {
timer.start();
}

public static void main(final String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
DTSCTest demo = new DTSCTest(TITLE);
demo.pack();
UIUtils.centerFrameOnScreen(demo);
demo.setVisible(true);
demo.start();
}
});
}
}
Ответ 2

Вы также можете сначала убрать ноль, advanceTime() затем appendData. (поменяйте местами способ, которым они это делают в примере).

Ответ 3

Одним из альтернативных подходов к ответу @thrashgod было бы использование TimeSeriesCollection и установка возраста элемента на TimeSeries. Приведенный ниже код позволяет настроить график для отображения данных за последний 1 час с интервалом в 1 минуту.

private TimeSeriesCollection dataset;
private TimeSeries sensorSeries;
sensorSeries = new TimeSeries("name", Minute.class);
sensorSeries.setMaximumItemAge(60);
dataset = new TimeSeriesCollection();
dataset.addSeries(sensorSeries);

.. и вы добавите данные по мере их поступления:

sensorSeries.add(new Minute(new Date()), newData);
2023-11-20 06:53 java