将串行通信数据添加到实时Java图中



现在我有一个可以读取串行数据的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()在事件调度线程上运行。

相关内容

  • 没有找到相关文章

最新更新