现在我有一个可以读取串行数据的Java文件,它只是在控制台中打印它。在另一个文件中,我有一个JFreeChart图,它将随机数据生成为实时图。
这两个文件都在同一个项目中。我如何将串行数据添加到实时图中,而不是我现在使用的随机数据?
下面的第一个代码是实时图形的文件。
public class test224 extends ApplicationFrame implements ActionListener {
String s;
String tempbuff;
private TimeSeries series;
private double lastValue = 10.0;
private Timer timer = new Timer(1000, this);
DynamicTimeSeriesCollection dataset;
float[] newData = new float[1];
public test224(final String title) {
super(title);
this.series = new TimeSeries("Sensor Value", Millisecond.class);
final TimeSeriesCollection dataset = new TimeSeriesCollection(this.series);
final JFreeChart chart = createChart(dataset);
timer.setInitialDelay(1000);
chart.setBackgroundPaint(Color.LIGHT_GRAY);
final JPanel content = new JPanel(new BorderLayout());
final ChartPanel chartPanel = new ChartPanel(chart);
content.add(chartPanel);
chartPanel.setPreferredSize(new java.awt.Dimension(800, 500));
setContentPane(content);
timer.start();
}
private JFreeChart createChart(final XYDataset dataset) {
final JFreeChart result = ChartFactory.createTimeSeriesChart(
"Dynamic Line Chart of Arduino Data",
"Zeit",
"Wert",
dataset,
true,
true,
false
);
final XYPlot plot = result.getXYPlot();
plot.setBackgroundPaint(new Color(0xffffe0));
plot.setDomainGridlinesVisible(true);
plot.setDomainGridlinePaint(Color.lightGray);
plot.setRangeGridlinesVisible(true);
plot.setRangeGridlinePaint(Color.lightGray);
ValueAxis xaxis = plot.getDomainAxis();
xaxis.setAutoRange(true);
xaxis.setFixedAutoRange(60000.0);
xaxis.setVerticalTickLabels(true);
ValueAxis yaxis = plot.getRangeAxis();
yaxis.setRange(0.0, 300.0);
return result;
}
public void actionPerformed(final ActionEvent e) {
final double factor = 0.9 + 0.2*Math.random();
this.lastValue = this.lastValue * factor;
final Millisecond now = new Millisecond();
this.series.add(new Millisecond(), this.lastValue);
}
public static void main(final String[] args) {
final test224 demo = new test224("Dynamic Line And TimeSeries Chart");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
在执行的操作中,生成随机数据。然后在另一个文件的这段代码中,它将Arduino串行数据打印到控制台,那么我如何才能让它显示在实时图中呢?
public synchronized void serialEvent(SerialPortEvent oEvent) {
if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
try {
inputLine=input.readLine();
System.out.println(inputLine);
}
catch (Exception e) {
}
}
}
您需要通过合并类将serialEvent
的内容移动到actionPerformed
方法中,或者在test224
中提供一个public addDataPoint(double point)
方法,该方法可以从包含串行事件的类中调用。我认为,在任何一种情况下,您都需要将serialEvent中的处理转移到一个单独的线程中。
你可以试试这样的东西:
@Override
public void actionPerformed(final ActionEvent e) {
//Initialise the serial port here before starting the new thread
Runnable task = new Runnable() {
@Override
public void run() {
if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
try {
inputLine = input.readLine();
System.out.println( inputLine );
final Millisecond now = new Millisecond();
series.add(new Millisecond(), Double.parseDouble(inputLine));
} catch (Exception e) {
}
}
}
};
Thread serialThread = new Thread(task);
serialThread.start();
}
public addDataPoint(double point)
解决方案更可取,因为您需要保持关注点的分离。
public synchronized void serialEvent(SerialPortEvent oEvent) {
if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
try {
inputLine=input.readLine();
System.out.println(inputLine);
dataChart.addPoint(Double.parseDouble(inputLin));
} catch (Exception e) {
}
}
}
您仍然需要确保在单独的线程上监视串行点。
如果不将调用封装在适合invokeLater()
的Runnable
中,我不愿意更新图表的数据集。此示例从匿名后台线程更新TableModel
。
更好的是,使用SwingWorker
,如图所示。您可以操作doInBackground()
方法中的串行端口和publish()
有用的结果,确信process()
在事件调度线程上运行。