使用JFreeChart和滑块更新图形 [英] Update graph with JFreeChart and slider

查看:131
本文介绍了使用JFreeChart和滑块更新图形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个描述管道压力的阵列的时间历史。因此,对于每个delta t,我有一个沿着管道长度的压力值阵列。我想使用JFreeChart绘制管道长度上的压力,并选择使用滑块绘制哪个delta t,以便每当用户移动滑块时,图形将以不同的delta t值更新。我还将瓦片重置为管道最后一部分的压力。发生的是标题是更新,意味着数据正在更新,但曲线保持不变。我已经阅读了论坛上的所有可能的主题,并尝试了我能想到的一切,但它不工作!这是我的类扩展JPanel的代码,其中方法jSlider1StateChanged听到滑块位置的变化,createChart创建者在程序启动时创建一个新的图表,dataSetGen(int ndt)基于滑块位置生成图形的新数据集:

  public class MyMainPanel extends JPanel {

private JFreeChart jc;
private OutputPipe op;
private DefaultXYDataset ds;
private javax.swing.JFrame jFrame1;
private javax.swing.JSlider jSlider1;
private pipevisualizer.MyChartPanel pnlChartPanel;

private void jSlider1StateChanged(javax.swing.event.ChangeEvent evt){
int ndt =((JSlider)evt。
getSource())。
getValue();
System.out.println(Slider1:+((JSlider)evt。
getSource())
getValue());

dataSetGen(ndt);
int a = 0;
jc.fireChartChanged();
}

private void dataSetGen(int ndt){
ArrayList< OutputPipeDt> opDtArray = op.getOpLit();
OutputPipeDt opDt = opDtArray.get(ndt);

double [] H = opDt.getH();
double [] l = new double [H.length];
double [] p = new double [H.length];
double dX = op.getPipeLength()/ H.length;
double slope = op.getPipeSlope();
double el = op.getPipeUSElev(); (int i = 0; i< H.length; i ++){
l [i] = dX * i;


p [i] = el - dX * slope * i;
}

double [] [] dataH = new double [2] [H.length];
dataH [0] = l;
dataH [1] = H;

double [] [] dataP = new double [2] [H.length];
dataP [0] = l;
dataP [1] = p;

ds = new DefaultXYDataset();
ds.addSeries(pipe head,dataH);
ds.addSeries(pipe profile,dataP);

jc.setTitle(H [end] =+ Double.toString(dataH [1] [l.length - 1]));
jc.fireChartChanged();
}

private JFreeChart createChart(OutputPipe op,int ndt){

ArrayList< OutputPipeDt> opDtArray = op.getOpLit();
OutputPipeDt opDt = opDtArray.get(ndt);

double [] H = opDt.getH();
double [] l = new double [H.length];
double [] p = new double [H.length];
double dX = op.getPipeLength()/ H.length;
double slope = op.getPipeSlope();
double el = op.getPipeUSElev(); (int i = 0; i< H.length; i ++){
l [i] = dX * i;


p [i] = el - dX * slope * i;
}

double [] [] dataH = new double [2] [H.length];
dataH [0] = l;
dataH [1] = H;

double [] [] dataP = new double [2] [H.length];
dataP [0] = l;
dataP [1] = p;

DefaultXYDataset ds = new DefaultXYDataset();
ds.addSeries(pipe head,dataH);
ds.addSeries(pipe profile,dataP);


JFreeChart图表= ChartFactory.createXYLineChart(
t =+ Double.toString(op.getOpLit()。get(ndt).getT()),
//图表标题
X,
// x轴标签
Y,
// y轴标签
ds,
// data
PlotOrientation.VERTICAL,
true,
// include legend
true,
// tooltips
false // urls
);

返回图表;
}
}

我认为对数据集的任何更改都会使图重绘本身。
对不起,如果代码可能大到这个帖子,但我不知道我应该粘贴哪些部分或多或少清楚。

解决方案

没有一个完整的例子,您可能可以使用显示的方法这里;它使用 plot.setDataset()替换接收每个事件的数据集。



附录:此示例显示随着时间的推移,温度与长度可能会让您开始。



  import java.awt.BorderLayout; 
import java.awt.Dimension;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

/ **
* @see https://stackoverflow.com/a/15207445/230513
* /
public class ChartSliderTest {

private static final int N = 25;
private static final double K = 273.15;
private static final Random random = new Random();

private static XYDataset getDataset(int n){

final XYSeries series = new XYSeries(Temp(K°));
双温; (int length = 0; length< N; length ++)
{
temperature = K + n * random.nextGaussian();
series.add(length + 1,temperature);
}
返回新的XYSeriesCollection(系列);
}

private static JFreeChart createChart(final XYDataset dataset){
JFreeChart图= ChartFactory.createXYLineChart(
ChartSliderTest,Length(m), Temp(K°),数据集,
PlotOrientation.VERTICAL,false,false,false);
返回图表;
}

private static void display(){
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final列表< XYDataset> list = new ArrayList< XYDataset>(); (int i = 0; i< = 10; i ++)
{
list.add(getDataset(i));
}
JFreeChart图= createChart(list.get(5));
final XYPlot plot =(XYPlot)chart.getPlot();
plot.getRangeAxis()。setRangeAboutValue(K,K / 5);
ChartPanel chartPanel = new ChartPanel(chart){
@Override
public Dimension getPreferredSize(){
return new Dimension(800,400);
}
};
f.add(chartPanel);
final JSlider slider = new JSlider(0,10);
slider.addChangeListener(new ChangeListener(){
@Override
public void stateChanged(ChangeEvent e){
plot.setDataset(list.get(slider.getValue())) ;
}
});
Box p = new Box(BoxLayout.X_AXIS);
p.add(new JLabel(Time:));
p.add(slider);
f.add(p,BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}

public static void main(String [] args){
EventQueue.invokeLater(new Runnable(){
@Override
public void run (){
display();
}
});
}
}


I have a time history for arrays describing the pressure along a pipe. So I have an array of pressure values along the length of the pipe for each delta t. I want to plot the pressures along the length of the pipe with JFreeChart and chose which delta t to plot with a slider, so that whenever the user moves the slider the graphic is updates with values from a different delta t. I'm also resetting the tile to be the pressure at the last portion of the pipe. What happens is that the title is updates, meaning the data is being properly updates, but the curve remains the same. I have read every possible topic on forums and tried everything I could think of but it's not working! Here's the code of my class that extends JPanel, in which the method jSlider1StateChanged hears the change in the slider position, createChart creaters a new chart when the program is started, and dataSetGen(int ndt) generates the graph's new dataset based on the slider position:

public class MyMainPanel extends JPanel {

  private JFreeChart jc;
  private OutputPipe op;
  private DefaultXYDataset ds; 
  private javax.swing.JFrame jFrame1;
  private javax.swing.JSlider jSlider1;
  private pipevisualizer.MyChartPanel pnlChartPanel;                       

  private void jSlider1StateChanged(javax.swing.event.ChangeEvent evt) {                                      
        int ndt = ((JSlider) evt.
                getSource()).
                getValue();
        System.out.println("Slider1: " + ((JSlider) evt.
                getSource()).
                getValue());

        dataSetGen(ndt);
        int a = 0;
        jc.fireChartChanged();
  }                

  private void dataSetGen(int ndt) {
        ArrayList<OutputPipeDt> opDtArray = op.getOpLit();
        OutputPipeDt opDt = opDtArray.get(ndt);

        double[] H = opDt.getH();
        double[] l = new double[H.length];
        double[] p = new double[H.length];
        double dX = op.getPipeLength() / H.length;
        double slope = op.getPipeSlope();
        double el = op.getPipeUSElev();

        for (int i = 0; i < H.length; i++) {
              l[i] = dX * i;
              p[i] = el - dX * slope * i;
        }

        double[][] dataH = new double[2][H.length];
        dataH[0] = l;
        dataH[1] = H;

        double[][] dataP = new double[2][H.length];
        dataP[0] = l;
        dataP[1] = p;

        ds = new DefaultXYDataset();
        ds.addSeries("pipe head", dataH);
        ds.addSeries("pipe profile", dataP);

        jc.setTitle("H[end] = " + Double.toString(dataH[1][l.length - 1]));
        jc.fireChartChanged();
  }

  private JFreeChart createChart(OutputPipe op, int ndt) {

        ArrayList<OutputPipeDt> opDtArray = op.getOpLit();
        OutputPipeDt opDt = opDtArray.get(ndt);

        double[] H = opDt.getH();
        double[] l = new double[H.length];
        double[] p = new double[H.length];
        double dX = op.getPipeLength() / H.length;
        double slope = op.getPipeSlope();
        double el = op.getPipeUSElev();

        for (int i = 0; i < H.length; i++) {
              l[i] = dX * i;
              p[i] = el - dX * slope * i;
        }

        double[][] dataH = new double[2][H.length];
        dataH[0] = l;
        dataH[1] = H;

        double[][] dataP = new double[2][H.length];
        dataP[0] = l;
        dataP[1] = p;

        DefaultXYDataset ds = new DefaultXYDataset();
        ds.addSeries("pipe head", dataH);
        ds.addSeries("pipe profile", dataP);


        JFreeChart chart = ChartFactory.createXYLineChart(
                "t = " + Double.toString(op.getOpLit().get(ndt).getT()),
                // chart title
                "X",
                // x axis label
                "Y",
                // y axis label
                ds,
                // data
                PlotOrientation.VERTICAL,
                true,
                // include legend
                true,
                // tooltips
                false // urls
                );

        return chart;
  }
}

I thought that any changes to the datasets would make the graph redraw itself. Sorry if the code might be to big to be on the post, but I don't know exactly which parts should I paste to be more or less clear.

解决方案

Absent a complete example, you may be able to use the approach shown here; it uses plot.setDataset() to replace the dataset on receiving each event.

Addendum: This example that shows temperature versus length over time may get you started.

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

/**
 * @see https://stackoverflow.com/a/15207445/230513
 */
public class ChartSliderTest {

    private static final int N = 25;
    private static final double K = 273.15;
    private static final Random random = new Random();

    private static XYDataset getDataset(int n) {

        final XYSeries series = new XYSeries("Temp (K°)");
        double temperature;
        for (int length = 0; length < N; length++) {
            temperature = K + n * random.nextGaussian();
            series.add(length + 1, temperature);
        }
        return new XYSeriesCollection(series);
    }

    private static JFreeChart createChart(final XYDataset dataset) {
        JFreeChart chart = ChartFactory.createXYLineChart(
            "ChartSliderTest", "Length (m)", "Temp (K°)", dataset,
            PlotOrientation.VERTICAL, false, false, false);
        return chart;
    }

    private static void display() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final List<XYDataset> list = new ArrayList<XYDataset>();
        for (int i = 0; i <= 10; i++) {
            list.add(getDataset(i));
        }
        JFreeChart chart = createChart(list.get(5));
        final XYPlot plot = (XYPlot) chart.getPlot();
        plot.getRangeAxis().setRangeAboutValue(K, K / 5);
        ChartPanel chartPanel = new ChartPanel(chart) {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(800, 400);
            }
        };
        f.add(chartPanel);
        final JSlider slider = new JSlider(0, 10);
        slider.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                plot.setDataset(list.get(slider.getValue()));
            }
        });
        Box p = new Box(BoxLayout.X_AXIS);
        p.add(new JLabel("Time:"));
        p.add(slider);
        f.add(p, BorderLayout.SOUTH);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                display();
            }
        });
    }
}

这篇关于使用JFreeChart和滑块更新图形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆