Java 更新JFreeChart时保留用户缩放状态
我正在使用Java 更新JFreeChart时保留用户缩放状态,java,jfreechart,Java,Jfreechart,我正在使用JFreeChart 1.0.14绘制XYSeries。我确实可以访问所有元素(ChartPanel,JFreeChart,XYSeriesCollection,XYSeries)。有时会有新的数据要绘制,所以我会更新我的系列(为了简单起见,假设只有一个系列): SwingUtilities.invokeLater(新的Runnable(){ @凌驾 公开募捐{ XYSeries xyData=新的XYSeries(“跟踪”); 对于(int i=0;i
JFreeChart 1.0.14
绘制XYSeries
。我确实可以访问所有元素(ChartPanel
,JFreeChart
,XYSeriesCollection
,XYSeries
)。有时会有新的数据要绘制,所以我会更新我的系列(为了简单起见,假设只有一个系列):
SwingUtilities.invokeLater(新的Runnable(){
@凌驾
公开募捐{
XYSeries xyData=新的XYSeries(“跟踪”);
对于(int i=0;i
这非常有效。但我有一个问题。用户可以通过在绘图中拖动进行缩放。每次数据更新时,此缩放都会重置。这很有意义,因为我创建了新的轴。如何保持用户缩放状态?由于用户也可以选择autorange/range,因此我不想对这些(Axis#setRange/setAutoRange
)进行任何攻击。我找到了一些关于图表面板#getScaleX()
的信息。但在上述调用器的开头总是1.0
。我也找不到任何图表面板.setScaleX
我是否做错了什么,或者是否有其他方法可以在不更改轴的范围/自动范围行为的情况下保持用户缩放状态
顺便说一句:我需要重新创建轴,因为它们也可以在logscale和linscale之间切换。我不认为每次添加新点或调用
removeAllSeries()
时都需要创建新的XYSeries xyData
此示例显示如何将动态数据添加到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。每次单击“添加新数据项”时,都会添加一个新点。在本例中,添加数据点时将保留缩放,但更改轴时不保留缩放
要在将轴从正常比例更改为对数比例时保持缩放,请使用两个轴的当前上限和下限,并设置新轴的
范围,如updateZoom
所示。我不知道如何将“用户缩放状态”从一个轴切换到另一个轴。因此,如果不需要,我确保不刷新轴(=对数/线性之间的比例没有变化)。如果有更改,用户缩放状态将丢失,这是不幸的。但这种情况并不经常发生,而且是由用户控制的,因此用户可能对缩放状态重置没有问题。不幸的是,这对我没有帮助,因为在您的示例中保留缩放的原因是轴没有更新。我不能这样做(正如我在问题中提到的)。我认为,这与我创建一个新系列无关。此外,我的应用程序在其集合中可以有无限数量的系列(它们在运行时被添加/删除),因此我不能只处理一组固定的系列,而从不在集合中添加/删除它们。不过,感谢您的贡献。:)@brimborium您是否可以使用Runnable
中的collection.getSeries(“”
)来获取要更新的序列?这样你就不必把这个系列变成一个属性了。我不明白。我不只是在我的系列中添加一些点,还有全新的系列要显示,有时它们会替换已经显示的系列(在这种情况下,我不必删除旧的系列),有时,它们会被添加(而显示的系列仍保留)。
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);
}
}