Chcę dodawać punkty (współrzędne) do serii punktów obiektów JFreeChart w oddzielnym wątku. Na razie robię to w while. Ale chcę to robić w oddzielnym wątku i na nowo wyświetlać cały wykres od nowa np co sekundę, dodając nowy punkt, z tego co wiem to nie mogę robić tego inaczej niż cały na nowo.

 package pl.rychlinski.damian;

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.ValueAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.*;
import java.util.List;

//TODO: Statystyki sekwencji z rozpoznanymi i błędnymi
public class MainFrame extends JFrame {

    private JButton btnWybPlik;
    private JLabel jlDroga;
    private JLabel jlPredkosc;
    private JLabel jlCzas;
    private JPanel mainjpanel;
    private JPanel jpMenu;
    private JPanel jpTablica;

    //private String sciezkaPliku;
    private SekwencjaGGA sekGGA = null;
    private SekwencjaGGA popSekGGA = null;
    private SekwencjaGSA sekGSA;
    private SekwencjaGLL sekGLL;
    private SekwencjaRMC sekRMC;

    private double droga;
    private double predkosc;

    private XYSeries series1;
    private XYSeriesCollection dataset;

    public MainFrame() {
        droga = 0;
        btnWybPlik.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JFileChooser fileChooser = new JFileChooser();
                fileChooser.setCurrentDirectory(new File(System.getProperty("user.home")));
                int result = fileChooser.showOpenDialog(mainjpanel);
                if (result == JFileChooser.APPROVE_OPTION) {
                    File selectedFile = fileChooser.getSelectedFile();
                    //System.out.println("Selected file: " + selectedFile.getAbsolutePath());
                    String sciezkaPliku = selectedFile.getAbsolutePath();
                    wczytaniePliku(sciezkaPliku);
                }
            }
        });

        jpTablica = new JPanel();
        mainjpanel.add(jpTablica);

        this.series1 = new XYSeries("Trasa", false);

        final XYSeriesCollection dataset = new XYSeriesCollection(this.series1);
        final JFreeChart chart = createChart(dataset);
        final ChartPanel chartPanel = new ChartPanel(chart);
        jpTablica.add(chartPanel);
    }

    private void wczytaniePliku(String sciezkaDoPliku) {
        try (BufferedReader br = new BufferedReader(new FileReader(sciezkaDoPliku))) {
            String line;
            //series1.add(53.448, 14.4907);
            while ((line = br.readLine()) != null) {
                parseLine(line);
            }
            //series1.add(53.4485, 14.4910);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void parseLine(String line) {
        String bezSumKont = line.substring(0, line.length() - 3);
        List<String> podzSekw = Arrays.asList(bezSumKont.split(","));

        if (podzSekw.get(0).equalsIgnoreCase("$GPGGA")) {
            if (check(line)) {
                if (sekGGA != null)
                    popSekGGA = sekGGA;

                sekGGA = new SekwencjaGGA(podzSekw);
                if (popSekGGA != null) {
                    droga += obliczOdleglosc(popSekGGA, sekGGA);
                    jlDroga.setText(String.valueOf(droga));
                }

                series1.add(sekGGA.getWspolzedne().getLongitude(), sekGGA.getWspolzedne().getLatitude());
                System.out.println(sekGGA.getWspolzedne().getLatitude() + " " + sekGGA.getWspolzedne().getLongitude());
                //System.out.println(series1.getMaxY() + " " + series1.getMinY());
            } else {
                //TODO: Zlicz błąd
            }
        }
        if (podzSekw.get(0).equalsIgnoreCase("$GPGSA")) {
            if (check(line)) {
                sekGSA = new SekwencjaGSA(podzSekw);
            } else {
                //TODO: Zlicz błąd
            }
        }
        if (podzSekw.get(0).equalsIgnoreCase("$GPGLL")) {
            if (check(line)) {
                sekGLL = new SekwencjaGLL(podzSekw);
            } else {
                //TODO: Zlicz błąd
            }
        }
        if (podzSekw.get(0).equalsIgnoreCase("$GPRMC")) {
            //TODO: Sekwencja RMC (Recommended minimum of data)
            if (check(line)) {
                sekRMC = new SekwencjaRMC(podzSekw);
            } else {
                //TODO: Zlicz błąd
            }
        }
    }

    private double obliczOdleglosc(SekwencjaGGA pkt1, SekwencjaGGA pkt2) {
        double odleglosc = 0;

        double earthRadius = 6371000; //meters
        double dLat = Math.toRadians(pkt2.getWspolzedne().getLatitude() - pkt1.getWspolzedne().getLatitude());
        double dLng = Math.toRadians(pkt2.getWspolzedne().getLongitude() - pkt1.getWspolzedne().getLongitude());
        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
                Math.cos(Math.toRadians(pkt1.getWspolzedne().getLatitude())) * Math.cos(Math.toRadians(pkt1.getWspolzedne().getLatitude())) *
                        Math.sin(dLng / 2) * Math.sin(dLng / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        odleglosc = earthRadius * c;

        return odleglosc;
    }

    /**
     * Funkcja sprawdzająca sume kontrolną
     *
     * @param tekst cała linia NMEA
     * @return true jeśli się suma kontrolna zgadza
     */
    private boolean check(String tekst) {
        String suma = tekst.substring(tekst.length() - 2, tekst.length());
        tekst = tekst.substring(1, tekst.length() - 3);

        int checksum = 0;
        for (int i = 0; i < tekst.length(); i++) {
            checksum = checksum ^ tekst.charAt(i);
        }

        if (Integer.parseInt(suma, 16) == checksum) {
            return true;
        }

        return false;
    }

    private JFreeChart createChart(final XYDataset dataset) {
        final JFreeChart result = ChartFactory.createXYLineChart(
                "Dynamic Data Demo",
                "Time",
                "Value",
                dataset);
        final XYPlot plot = result.getXYPlot();
        //ValueAxis axis = plot.getDomainAxis();
        //axis.setAutoRange(true);
        NumberAxis yAxis = (NumberAxis) plot.getRangeAxis();
        yAxis.setAutoRangeIncludesZero(false);
        yAxis.setAutoRange(true);

        customizeChart(result);
        //axis.setFixedAutoRange(60000.0);  // 60 seconds
        //axis = plot.getRangeAxis();
        //axis.setRange(0.0, 200.0);
        return result;
    }

    private void customizeChart(JFreeChart chart) {
        XYPlot plot = chart.getXYPlot();

        XYLineAndShapeRenderer renderer;
        renderer = new XYLineAndShapeRenderer(true, true);
        renderer.setSeriesShapesVisible(0, true);
        renderer.setSeriesShapesVisible(1, false);

        // sets paint color for each series
        renderer.setSeriesPaint(0, Color.RED);
        renderer.setSeriesPaint(1, Color.BLUE);

        // sets thickness for series (using strokes)
        renderer.setSeriesStroke(0, new BasicStroke(1.0f));
        renderer.setSeriesStroke(1, new BasicStroke(1.0f));

        // sets paint color for plot outlines
        //plot.setOutlinePaint(Color.BLUE);
        //plot.setOutlineStroke(new BasicStroke(2.0f));

        // sets renderer for lines
        plot.setRenderer(renderer);

        // sets plot background
        plot.setBackgroundPaint(Color.WHITE);

        // sets paint color for the grid lines
        plot.setRangeGridlinesVisible(true);
        plot.setRangeGridlinePaint(Color.BLACK);

        plot.setDomainGridlinesVisible(true);
        plot.setDomainGridlinePaint(Color.BLACK);
    }


    public static void main(String[] args) {
        JFrame frame = new JFrame("MainFrame");
        frame.setContentPane(new MainFrame().mainjpanel);
        frame.setPreferredSize(new Dimension(640, 480));
        frame.pack();
        frame.setVisible(true);
    }

    {
// GUI initializer generated by IntelliJ IDEA GUI Designer
// >>> IMPORTANT!! <<<
// DO NOT EDIT OR ADD ANY CODE HERE!
        $$$setupUI$$$();
    }

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     *
     * @noinspection ALL
     */
    private void $$$setupUI$$$() {
        mainjpanel = new JPanel();
        mainjpanel.setLayout(new BorderLayout(0, 0));
        jpMenu = new JPanel();
        jpMenu.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
        mainjpanel.add(jpMenu, BorderLayout.NORTH);
        btnWybPlik = new JButton();
        btnWybPlik.setHorizontalAlignment(0);
        btnWybPlik.setText("Wybierz");
        btnWybPlik.setVerticalAlignment(0);
        jpMenu.add(btnWybPlik);
        final JLabel label1 = new JLabel();
        label1.setText("Droga:");
        jpMenu.add(label1);
        jlDroga = new JLabel();
        jlDroga.setText("0");
        jpMenu.add(jlDroga);
        final JLabel label2 = new JLabel();
        label2.setText("Prędkość:");
        jpMenu.add(label2);
        jlPredkosc = new JLabel();
        jlPredkosc.setText("0");
        jpMenu.add(jlPredkosc);
        final JLabel label3 = new JLabel();
        label3.setText("Czas:");
        jpMenu.add(label3);
        jlCzas = new JLabel();
        jlCzas.setText("0");
        jpMenu.add(jlCzas);
        jpTablica = new JPanel();
        jpTablica.setLayout(new com.intellij.uiDesigner.core.GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
        mainjpanel.add(jpTablica, BorderLayout.CENTER);
    }

    /**
     * @noinspection ALL
     */
    public JComponent $$$getRootComponent$$$() {
        return mainjpanel;
    }
}