-1

I make a JFreeChart for displaying values from serial port. It is working well, but I want to make X-axis movable from right to left. It means when plotting the graph, custom values or seconds move from right to left; now it work as 0 of x-axis remains same place, but I want to move from left right to left continuously. Also I tried createTimeSeriesChart, but it is start from 0 then 59 again start to 0, but I want continuous running of seconds 0 to onwards.

`import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Scanner;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.general.Series;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

//import org.jfree.chart.ChartFactory;
//import org.jfree.chart.ChartPanel;
//import org.jfree.chart.JFreeChart;
//import org.jfree.data.xy.XYSeries;
//import org.jfree.data.xy.XYSeriesCollection;

import com.fazecast.jSerialComm.SerialPort;


public class AccelerometerGraph {
    
    static SerialPort chosenPort;
    static int x = 0;

public static void main(String[] args) {
        
        // create and configure the window
        JFrame window = new JFrame();
        window.setTitle("Vibration Analyzer Graph GUI");
        window.setSize(600, 400);
        window.setLayout(new BorderLayout());
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        // create a drop-down box and connect button, then place them at the top of the window
        JComboBox<String> portList = new JComboBox<String>();
        JButton connectButton = new JButton("Connect");
        JTextField textField = new JTextField(10);
        JLabel label = new JLabel();
        JPanel topPanel = new JPanel();
        JPanel bottomPanel = new JPanel();
        label.setText("Accel Values");
        textField.setFocusable(false);
        topPanel.add(portList);
        topPanel.add(connectButton);
        bottomPanel.add(label);
        bottomPanel.add(textField); 
        window.add(topPanel, BorderLayout.NORTH);
        window.add(bottomPanel, BorderLayout.SOUTH);
        
        // populate the drop-down box
        SerialPort[] portNames = SerialPort.getCommPorts();
        for(int i = 0; i < portNames.length; i++)
            portList.addItem(portNames[i].getSystemPortName());
        
        
        // create the line graph
        XYSeries series = new XYSeries("");
        XYSeriesCollection dataset = new XYSeriesCollection(series);
        JFreeChart chart = ChartFactory.createXYLineChart("Accelerometer Readings", "Time (seconds)", "Intensity cm/s", dataset);
        window.add(new ChartPanel(chart), BorderLayout.CENTER);
        
        // configure the connect button and use another thread to listen for data
        connectButton.addActionListener(new ActionListener(){
            @Override public void actionPerformed(ActionEvent arg0) {
                if(connectButton.getText().equals("Connect")) {
                    // attempt to connect to the serial port
                    chosenPort = SerialPort.getCommPort(portList.getSelectedItem().toString());
                    chosenPort.setComPortTimeouts(SerialPort.TIMEOUT_SCANNER, 0, 0);
                    if(chosenPort.openPort()) {
                        connectButton.setText("Disconnect");
                        portList.setEnabled(false);
                    }
                    
                    
                    // create a new thread that listens for incoming text and populates the graph
                    Thread thread = new Thread(){
                        @Override public void run() {
                            Scanner scanner = new Scanner(chosenPort.getInputStream());
                        
                            while(scanner.hasNextLine()) {
                                try {
                                    String line = scanner.nextLine();
                                    int number = Integer.parseInt(line);                                                                
                                    series.add(x++, 1023 - number);                                         
                                    textField.setText(String.valueOf(line));                                    
                                    window.repaint();
                                } catch(Exception e) {}
                            }
                            scanner.close();
                        }
                    };
                    thread.start();
                } else {
                    // disconnect from the serial port
                    chosenPort.closePort();
                    portList.setEnabled(true);
                    connectButton.setText("Connect");
                    textField.setText(null);
                    series.clear();
                    x = 0;
                }
            }
        });
        
        // show the window
        window.setVisible(true);
    }

}

`

trashgod
  • 200,320
  • 28
  • 229
  • 974
  • 1
    I'd suggest handling data acquisition like [this](https://stackoverflow.com/a/13205322/230513); few readers will have your setup, so you may want to mock the data; more on time series [here](https://stackoverflow.com/q/5048852/230513); pan and zoom like [this](https://stackoverflow.com/a/44151032/230513). – trashgod May 14 '22 at 22:21
  • Thank you for reply, I visited all your links but I want only to Auto Scroll X-axis to left side when reading values by serial port. Now the x-axis zero is still on its position but I only need to change in my code that is auto scrolling x-axis? – Imran Ahmed May 17 '22 at 21:58
  • You might look at the domain scrolling alternatives mentioned [here](https://stackoverflow.com/a/44105790/230513), but the incorrect synchronization will remain a technical debt – trashgod May 17 '22 at 22:05

1 Answers1

-1

As you observed here, you are missing data from the serial port. As noted here and here, the problem is likely due to incorrect use of concurrency. Instead, extend SwingWorker, as shown here:

image

Poll (or listen) to the device in your implementation of doInBackground(), where the worker thread can safely block. When new data is available, publish() the result. Your implementation of process() will then see the new data on the event dispatch thread, where it is safe to update the chart's dataset. The chart will update itself in response.

If you still have trouble, update your question with this much smaller example. Placing your code for reading the device in doInBackground(). For reference, this related example illustrates reading from an InputStream and updating an image.

@Override
protected Double doInBackground() throws Exception {
    while (…) {
        double x = …
        publish(x);
    }
    return x;
}

Regarding your use of a time series, instead of DynamicTimeSeriesCollection, consider TimeSeriesCollection, mentioned here. It is also dynamic and also more flexible.

trashgod
  • 200,320
  • 28
  • 229
  • 974