从线程更新JFreeChart

时间:2015-06-09 17:01:34

标签: java multithreading swing jfreechart

我必须建立一个GPS解析器。我需要在另一个线程中解析NMEA字符串,该线程将解析单个NMEA字符串并以1 Hz更新图表。现在我构建了部分代码,但是我在while循环中解析主线程中的数据;我的老师说这是错的。我在Java上编程,但在多线程方面没有。我如何将解析过程和刷新图表移到后台线程?

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) { ... }

    private void customizeChart(JFreeChart chart) { ... }    

    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);
    }

1 个答案:

答案 0 :(得分:2)

要避免阻止event dispatch thread,请构建SwingWorker的实例。在您的doInBackground()publish()中间结果的实施中收集数据,并更新XYSeries实施中的process()。听力图表将自行更新。使用的相关示例如下所示,并检查了here

image