1

现在我有一个可以读取串行数据的 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) {
        }
    }
}
4

2 回答 2

1

您需要通过合并类将您的内容移动serialEvent到您actionPerformed的方法中,或者提供一个可以从包含您的串行事件的类中调用的public addDataPoint(double point)方法。test224我认为无论哪种情况,您都需要将 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) {                             
        }
    }
}

您仍然需要确保在单独的线程上监视串行点。

于 2013-02-25T09:42:19.340 回答
1

如果不将调用包装在Runnable适合的invokeLater(). 此示例TableModel从匿名后台线程更新 a 。

更好的是,使用 a ,如此SwingWorker所示。您可以在方法和有用的结果中操作串口,确信在事件调度线程上运行。doInBackground()publish()process()

于 2013-02-25T23:21:24.553 回答