0

JFreeChart 1.0.14をプロットするために使用していますXYSeries。すべての要素 ( ChartPanelJFreeChartXYSeriesCollectionXYSeries) にアクセスできます。プロットする新しいデータが時々あるので、シリーズを更新します (簡単にするために、シリーズが 1 つだけあると仮定します)。

SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
        XYSeries xyData = new XYSeries("Trace");
        for (int i = 0; i < n; i++)
            xyData.add(data[0][i], data[1][i], false);

        collection.removeAllSeries();
        collection.addSeries(xyData);

        chart.getXYPlot().setRangeAxis(createNewAxis());
    }
});

これはすべてうまくいきます。しかし、私には1つの問題があります。ユーザーは、プロットをドラッグしてズームできます。このズームは、データが更新されるたびにリセットされます。新しい軸を作成するので、これは理にかなっています。ユーザーのズーム状態を保持するにはどうすればよいですか? ユーザーはオートレンジ/レンジも選択できるので、それらをハックしたくありません( Axis#setRange/setAutoRange)。について何かを見つけましたChartPanel#getScaleX()。しかし、これは常に1.0上記のinvokeLater. また、私は何も見つけることができませんChartPanel.setScaleX

何か間違ったことをしていますか、または軸の範囲/自動範囲の動作を変更せずにユーザーのズーム状態を保持する別の方法はありますか?

ところで:対数スケールとリンスケールを切り替えることもできるため、軸を再作成する必要があります

4

2 に答える 2

1

XYSeries xyData新しいポイントを追加したり、電話をかけたりするたびに、新しいポイントを作成する必要はないと思いますremoveAllSeries()

この例は、動的データをに追加する方法を示していますXYSeriesCollection

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.LogAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.time.Millisecond;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;

/**
 * A demonstration application showing a XYseries chart where you can
 * dynamically add (random) data by clicking on a button.
 */
public class DynamicDataDemo1 extends ApplicationFrame {
    /**
     * Constructs a new demonstration application.
     * 
     * @param title
     *            the frame title.
     */
    public DynamicDataDemo1(String title) {
        super(title);
        MyDemoPanel demoPanel = new MyDemoPanel();
        setContentPane(demoPanel);
    }



    static class MyDemoPanel extends DemoPanel implements ActionListener {
        /** The time series data. */

        /** The most recent value added. */
        private double lastValue1 = 200.0;
        private double lastValue2 = 200.0;
        private XYPlot plot;
        private boolean logAxis = false;
        private String lastSeries = "";
        private final XYSeriesCollection dataset;
        private static String SERIES_NAME =  "Random Data ";
        private static int seriesNumber =  0;
        /**
         * Creates a new instance.
         */
        public MyDemoPanel() {
            super(new BorderLayout());
            lastSeries = SERIES_NAME + (seriesNumber++);
            XYSeries series = new XYSeries(lastSeries);
            dataset = new XYSeriesCollection(series);
            ChartPanel chartPanel = new ChartPanel(createChart(dataset));
            chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
            addChart(chartPanel.getChart());
            JPanel buttonPanel = new JPanel();
            buttonPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
            JButton button = new JButton("Add New Data Item");
            button.setActionCommand("ADD_DATA");
            button.addActionListener(this);
            buttonPanel.add(button);
            {
                JButton button2 = new JButton("Switch Axis");
                button2.setActionCommand("SWITCH_AXIS");
                button2.addActionListener(this);
                buttonPanel.add(button2);
            }
            {
                JButton button2 = new JButton("Add Series");
                button2.setActionCommand("ADD_SERIES");
                button2.addActionListener(this);
                buttonPanel.add(button2);
            }
            add(chartPanel);
            add(buttonPanel, BorderLayout.SOUTH);
        }

        private JFreeChart createChart(XYDataset dataset) {
            JFreeChart result = ChartFactory.createXYLineChart("Dynamic Data Demo", "Time", "Value", dataset, PlotOrientation.VERTICAL, true, true, false);
            plot = (XYPlot) result.getPlot();
            ValueAxis domainAxis = plot.getDomainAxis();
            domainAxis.setAutoRange(true);
            final ValueAxis rangeAxis = plot.getRangeAxis();
            rangeAxis.setAutoRange(true);
            return result;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (e.getActionCommand().equals("ADD_DATA")) {
                double factor1 = 0.90 + 0.2 * Math.random();
                double factor2 = 0.90 + 0.2 * Math.random();
                this.lastValue1 = this.lastValue1 * factor1;
                this.lastValue2 = this.lastValue2 * factor2;
                Millisecond now = new Millisecond();
                System.out.println("Now = " + now.toString());
                XYSeries series = dataset.getSeries(lastSeries);
                series.add(this.lastValue2, this.lastValue1);
            } else if (e.getActionCommand().equals("SWITCH_AXIS")) {
                if (!logAxis) {
                    LogAxis xAxis = new LogAxis("X");
                    LogAxis yAxis = new LogAxis("Y");               
                    updateZoom(xAxis,yAxis);
                logAxis = true;
                } else {
                    NumberAxis xAxis = new NumberAxis("X");
                    NumberAxis yAxis = new NumberAxis("Y");
                    updateZoom(xAxis,yAxis);
                    logAxis = false;
                }
            } else if (e.getActionCommand().equals("ADD_SERIES")) {
                lastSeries = SERIES_NAME + (seriesNumber++);
                XYSeries series = new XYSeries(lastSeries);
                dataset.addSeries(series);
            }
        }

        private void (ValueAxis xAxis, ValueAxis yAxis) {
            double domainMin = plot.getDomainAxis().getRange().getLowerBound();
            double domainMax = plot.getDomainAxis().getRange().getUpperBound();
            System.out.println(domainMin + "," + domainMax);

            double rangeMin = plot.getRangeAxis().getRange().getLowerBound();
            double rangeMax = plot.getRangeAxis().getRange().getUpperBound();
            System.out.println(rangeMin + "," + rangeMax);                  

            xAxis.setRange(domainMin, domainMax);
            plot.setDomainAxis(xAxis);
            yAxis.setRange(rangeMin, rangeMax);
            plot.setRangeAxis(yAxis);

        }
    }

    public static JPanel createDemoPanel() {
        return new DynamicDataDemo1.MyDemoPanel();
    }

    public static void main(String[] args) {
        DynamicDataDemo1 demo = new DynamicDataDemo1("JFreeChart: Dynamic XYSeries");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);
    }
}

この例は、JFreeChart:DynamicDataDemo1.javaに基づいています。「新しいデータ項目の追加」をクリックするたびに、新しいポイントが追加されます。この例では、データポイントを追加するときはズームが保持されますが、軸を変更するときは保持されません。

軸を通常から対数スケールに、またはその逆に変更するときにズームを維持するには、両方の軸から現在の上限と下限を使用し、Range次のように新しい軸のを設定します。updateZoom

于 2012-07-24T14:22:33.437 に答える
0

「ユーザーのズーム状態」をある軸から別の軸に引き継ぐ方法がわかりませんでした。したがって、必要がない場合は軸を更新しないようにしました (= 対数/線形の間でスケールを変更しません)。変更があった場合、残念ながらユーザーのズーム状態が失われます。しかし、それはそれほど頻繁には発生せず、ユーザーが制御するため、ユーザーはズーム状態をリセットしても問題ない場合があります。

于 2012-07-30T08:27:15.233 に答える