8

バックグラウンド計算の結果を表示する GUI を作成しています。しかしその前に、データセットの変更をテストしたかったのです。これが私のコードです:

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

ご覧のとおり、グラフ上のポイントを変更したい (「複雑な計算」が終了するたびに) - この変更は、別のクラスで私が呼び出したスレッドにあります。私の問題は、この概念全体が機能していないことです。「範囲外のシリーズインデックス」-IllegalArgumentException、「範囲外のインデックス」-一部のライブラリ内部配列リストなどをスローします.X軸を時間ではなく内部反復の数にする必要があるため、DynamicTimeSeriesCollectionを使用していませんまた、ある期間ごとではなく、「いくつかの計算」が終了したときにも更新します。私が間違っていることを教えてもらえますか?または、グラフを更新/更新するより良い方法はありますか?

4

1 に答える 1

11

スニペットが正しく同期されていません。ここに示すように、 a のメソッドdatasetから更新する必要があります。あなたのドメインは「私の内部反復の数」であるため、使用しないでください; 代わりに、に示すように を使用してください。process()SwingWorkerDateAxisNumberAxisChartFactory.createXYLineChart()

補遺: この例のバリエーションでは労働者の進捗状況が折れ線グラフにプロットされます。ドメインと範囲の両方をcreateXYLineChart()使用することに注意してください。NumberAxis折れ線seriesグラフのデータセットに が指定さprocess()れている場合、新しいデータが到着したときに の実装がデータセットを安全に更新する方法にも注意してください。リスニングチャートはそれに応じて更新されます。

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

チャート

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);
    }
}
于 2012-11-03T02:10:20.270 に答える