Zufällige Fehler beim Ändern von Reihen mit JFreeChart

Lesezeit: 5 Minuten

Zufallige Fehler beim Andern von Reihen mit JFreeChart
aragornsql

Ich mache eine GUI, die das Ergebnis von Hintergrundberechnungen anzeigt. Aber vorher wollte ich das Ändern des Datensatzes testen. Hier ist mein Code:

 DefaultXYDataset dataset = new DefaultXYDataset();
@Override
        public void run() {
                // TODO Auto-generated method stub
                for (int i = 0; i < periods; i++) {
                        series[0][i] = (double) i;
                        series[1][i] = 0;
                }
                dataset.addSeries("Series0", series);
                for (int it = 0; it < 10; it++) {
                        series[1][random.nextInt(periods)] =  random.nextInt(100) / 2;
                        double[][] d = new double[2][periods];
                        for (int i = 0; i < periods; i++) {
                                d[0][i] = series[0][i];
                                d[1][i] = series[1][i];
                        }
                        dataset.removeSeries("Series0");
                        dataset.addSeries("Series0", series);
//                      try {
//                              Thread.sleep(100);
//                      } catch (java.lang.InterruptedException ex) {
//                      }
                }

Wie Sie sehen können, möchte ich Punkte im Diagramm ändern (jedes Mal, wenn es “einige komplizierte Berechnungen” beendet) – diese Änderung befindet sich in dem von mir in einer anderen Klasse aufgerufenen Thread. Mein Problem ist, dass dieses ganze Konzept nicht funktioniert. Es wirft ‘Serienindex außerhalb der Grenzen’ – IllegalArgumentException, ‘Index außerhalb der Grenzen’ – einer inneren Arrayliste einer Bibliothek usw. Ich verwende DynamicTimeSeriesCollection nicht, da die X-Achse die Anzahl meiner inneren Iterationen und nicht die Zeit sein muss Zeitraum, und aktualisieren Sie auch, wenn “einige Berechnungen” abgeschlossen sind, nicht in jedem Zeitraum. Können Sie mir sagen, was ich falsch mache? Oder gibt es eine bessere Möglichkeit, das Diagramm zu aktualisieren/aktualisieren?

  • Sie müssen den entsprechenden Code hier mit Ihrer Frage posten. Am besten wäre so nah an einem scce wie du bekommen könntest.

    – Hovercraft voller Aale

    3. November 2012 um 2:00 Uhr

  • Ich bin mir nicht sicher, ob dies etwas ändert, da das Problem imo mit dem von mir bereitgestellten Code zusammenhängt. Aber solange Sie bereit sind, mir zu helfen, ist dies der vollständige Code:pastebin.com/zEBHZYj4 . Diese Klasse wird zu einigen JPanel hinzugefügt, ich rufe new Thread(JPaintablePanel).start(); mit einem Knopf

    – aragornsql

    3. November 2012 um 2:15 Uhr

Zufallige Fehler beim Andern von Reihen mit JFreeChart
Müllgott

Ihr Snippet ist falsch synchronisiert; du solltest deine aktualisieren dataset von dem process() Methode von a SwingWorker, wie hier gezeigt. Da Ihre Domäne “die Anzahl meiner inneren Iterationen” ist, verwenden Sie kein a DateAxis; Verwenden Sie stattdessen a NumberAxiswie gezeigt in ChartFactory.createXYLineChart().

Nachtrag: Diese Variation des Beispiels zeigt den Fortschritt des Arbeiters in einem Liniendiagramm. Beachten Sie, dass createXYLineChart() Verwendet NumberAxis sowohl für die Domäne als auch für den Bereich. Angenommen series Beachten Sie im Datensatz des Liniendiagramms auch, wie die Implementierung von process() kann den Datensatz sicher aktualisieren, wenn neue Daten eintreffen; Das Listening-Diagramm wird sich als Reaktion darauf aktualisieren.

private XYSeries series = new XYSeries("Result");
…
@Override
protected void process(List<Double> chunks) {
    for (double d : chunks) {
        label.setText(df.format(d));
        series.add(++n, d);
    }
}

Diagramm

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.beans.PropertyChangeEvent;
import java.text.DecimalFormat;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
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.plot.PlotOrientation;
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;

/**
 * @see https://stackoverflow.com/a/13205322/230513
 * @see https://stackoverflow.com/questions/4637215
 */
public final class ChartWorker {

    private static final String S = "0.000000000000000";
    private final JProgressBar progressBar = new JProgressBar();
    private final JLabel label = new JLabel(S, JLabel.CENTER);
    private final XYSeries series = new XYSeries("Result");
    private final XYDataset dataset = new XYSeriesCollection(series);

    private void create() {
        JFrame f = new JFrame("√2");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(progressBar, BorderLayout.NORTH);
        JFreeChart chart = ChartFactory.createXYLineChart(
            "Newton's Method", "X", "Y", dataset,
            PlotOrientation.VERTICAL, false, true, false);
        XYPlot plot = (XYPlot) chart.getPlot();
        plot.getRangeAxis().setRange(1.4, 1.51);
        plot.getDomainAxis().setStandardTickUnits(
            NumberAxis.createIntegerTickUnits());
        XYLineAndShapeRenderer renderer
            = (XYLineAndShapeRenderer) plot.getRenderer();
        renderer.setSeriesShapesVisible(0, true);
        f.add(new ChartPanel(chart) {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(640, 480);
            }
        }, BorderLayout.CENTER);
        f.add(label, BorderLayout.SOUTH);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
        runCalc();
    }

    private void runCalc() {
        progressBar.setIndeterminate(true);
        TwoWorker task = new TwoWorker();
        task.addPropertyChangeListener((PropertyChangeEvent e) -> {
            if ("progress".equals(e.getPropertyName())) {
                progressBar.setIndeterminate(false);
                progressBar.setValue((Integer) e.getNewValue());
            }
        });
        task.execute();
    }

    private class TwoWorker extends SwingWorker<Double, Double> {

        private static final int N = 5;
        private final DecimalFormat df = new DecimalFormat(S);
        double x = 1;
        private int n;

        @Override
        protected Double doInBackground() throws Exception {
            for (int i = 1; i <= N; i++) {
                x = x - (((x * x - 2) / (2 * x)));
                setProgress(i * (100 / N));
                publish(x);
                Thread.sleep(1000); // simulate latency
            }
            return x;
        }

        @Override
        protected void process(List<Double> chunks) {
            for (double d : chunks) {
                label.setText(df.format(d));
                series.add(++n, d);
            }
        }
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new ChartWorker()::create);
    }
}

  • Danke für Swingworker, ich werde es versuchen! Aber können Sie die Idee von Number/DateAxs erweitern? Wo wird es angezeigt und was muss ich ändern?

    – aragornsql

    3. November 2012 um 2:49 Uhr

  • @aragornsql: Ich habe oben näher darauf eingegangen.

    – Müllgott

    3. November 2012 um 10:38 Uhr

  • OK danke. Ich habe eine andere vielleicht nicht verwandte Frage. Ich muss ChartPanel in cardLayout verwenden, um zwischen den Diagrammen zu wechseln, wenn ich auf das Registerkartenfenster klicke. Ich habe es mit gewöhnlichem JPanel versucht (“öffentliche Klasse JPaintablePanel erweitert JPanel” – es zeigt je nach Registerkarte eine Schaltfläche mit unterschiedlichem Namen) und es funktioniert gut. Aber das gleiche mit “public class JPaintablePanel erweitert ChartPanel” funktioniert nicht, es zeigt nur einen Graphen. Können Sie mir sagen, wie man ChartPanell dazu zwingt, zu wechseln und Daten beizubehalten? pastebin.com/THuvGan5 ChartPanel, pastebin.com/Br2swZiC KartenLayout

    – aragornsql

    3. November 2012 um 11:01 Uhr


  • Als akzeptiert markiert. Nächste Frage hier: stackoverflow.com/questions/13208626/…

    – aragornsql

    3. November 2012 um 11:16 Uhr

1002190cookie-checkZufällige Fehler beim Ändern von Reihen mit JFreeChart

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy