使用不同的刷新率以dinamically方式更新XY线JFreeChart

时间:2016-06-29 17:05:18

标签: java swing jfreechart

我正在使用不同的“刷新率”绘制我要打印的JFreeChart。目前,我可以用“一次性”打印它,但是我无法用它打印它。刷新率我将其作为int值保存在我的代码中。

在打印之前,我进行所有计算然后打印。我现在要做的是计算时打印。只要我得到一个点的值,就打印出来,依此类推。

我的计算代码如下:

XYLineChart_AWT chartTemp = new XYLineChart_AWT();
int refreshRate = getRefreshRate();
for (int i = 0; i<MaxValue;i++) {
   //calculate values of Array1, Array2 and Array3
   chart1.setChart(chartTemp.runSimGraph("Title", "XLabel", "YLabel",true, new double[][]{Array1,Array2,Array3}));
}

但是,这只会在JFreeChart - 循环结束时打印for(在每次for迭代结束之前使用Thread.sleep()方法尝试)。

我怎样才能以动态方式打印图表?在计算值时是否需要更新数据集?如果是这样,我该怎么做?

编辑:我已经创建了一个可验证的小例子,我想要实现的目标。如果我按下按钮,而不是在计算完成时显示图表,它就会在完成时显示。我想要一种方法让它在计算后逐点显示出来。是的,每次迭代调用setChart()都非常无效。

代码: Test1.java

 package cenas;

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;

import net.miginfocom.swing.MigLayout;

public class Test1 extends JFrame 
{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    /**
     * 
     */
    private JTabbedPane tabbedBackground;



    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Test2 secondFrame = new Test2();
                    Test1 mainFrame = new Test1(secondFrame);
                    mainFrame.setVisible(true);
                    secondFrame.setVisible(true);
                    secondFrame.setLocationRelativeTo(null);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    public Dimension getPreferredSize() {
        // given some values of w & h
        return new Dimension(1000, 650);
    }

    /**
     * Create the frame.
     */
    public Test1(Test2 secondFrame) {

        this.setLocationByPlatform(true);
        setTitle("IMESS Simulator");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setMinimumSize(new Dimension(1000, 650));


        tabbedBackground = new JTabbedPane(JTabbedPane.TOP);
        setContentPane(tabbedBackground);
        initComponentsandRunSimulator(secondFrame);
        pack();
        //setResizable(false);

    }

    private void initComponentsandRunSimulator(Test2 frame2) {


        JPanel panel1 = new JPanel();
        tabbedBackground.addTab("Strategy and Results", null, panel1, null);
        tabbedBackground.setEnabledAt(0,true);
        panel1.setLayout(new MigLayout("", "[400.00px,grow]20[300px,grow]20[300.00px,grow]", "[40px,grow 20][][][][][100px,grow]20[20px]20[250.00px,grow]"));


        JButton myButton = new JButton("Button - Press me");
        myButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                frame2.setComponentsLists(100);
            }
        });

        //Add Simulation Panel to the layout
        panel1.add(myButton, "cell 1 1 2 5,grow");
    }

}

Test2.java

package cenas;

import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;

import org.jfree.chart.ChartPanel;


import net.miginfocom.swing.MigLayout;

public class Test2 extends JFrame{


    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private JTabbedPane tabbedBackground2;
    private ChartPanel chart1 = new ChartPanel (null);
    private int value;



    @Override
    public Dimension getPreferredSize() {
        // given some values of w & h
        return new Dimension(1000, 650);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Test2 frame = new Test2();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public void setComponentsLists(int refreshRate) {
        this.value=refreshRate;
        System.out.println("ola");
        simulateValues(refreshRate);
    }

    public Test2()  {
        setTitle("IMESS Simulator - Decision System");
        setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
        setLocationRelativeTo(null);
        setMinimumSize(new Dimension(1000, 650));

        tabbedBackground2 = new JTabbedPane(JTabbedPane.TOP);
        setContentPane(tabbedBackground2);
        initComponents();
        pack();
    }

private void initComponents() {

        // Panel
        JPanel panelSimulation = new JPanel();
        tabbedBackground2.addTab("Strategy and Results", null, panelSimulation, null);
        tabbedBackground2.setEnabledAt(0,true);
        panelSimulation.setLayout(new MigLayout("", "[400.00px,grow]20[300px,grow]20[300.00px,grow]", "[40px,grow 20][][][][][100px,grow]20[20px]20[250.00px,grow]"));

        chart1.setPopupMenu(null);
        chart1.setVisible(true);

        //Add Simulation Panel to the layout
        panelSimulation.add(chart1, "cell 0 2");
    }

private void simulateValues(int sliderValue) {



    double[] Array1 = new double[1440];
    double[] Array2 = new double[1440];
    double[] Array3 = new double[1440];
    for(int i = 0; i<1440; i++) {
        Array1[i]=0;
        Array2[i]=0;
        Array3[i]=0;
    }

    int peaks = 0;



    GraphTest chartTemp = new GraphTest();


    //Simulation for 24h (1 point per minute)
    for(int i = 0; i<1440; i++) {
        //Some calculations 
        if(i!=0)
            Array1[i]=Array1[i-1];

        if (((i>5) && (i<300)) || ((i>400) && (i<700)))
        {
            //Increase the energy per minute
            if((Array1[i]+10)<=50)
                Array1[i] = Array1[i]+ 10;

            else { //if we charge at normal rate, it could surpass capacity, so there may be leftovers
                Array1[i]=27;

            }       

        }

        if (peaks==0) {
            //Check if there is enough energy to supply in the ESS
            if(Array1[i]>Array2[i]) {

                Array3[i]=Array2[i]; //usage by the ESS
                Array2[i]=0; //Visualization purposes - grid does not provide any energy
                Array1[i]=Array1[i] - Array3[i]; //energy used by ESS

            }

        }

        chart1.setChart(chartTemp.runSimGraph("Title", "xLabel", "yLabel", true, new double[][]{Array1,Array2,Array3}));
    }


}


}

GraphTest.java

package cenas;

import java.awt.Color;
import java.awt.Shape;
import java.awt.geom.Rectangle2D;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.data.xy.XYDataset; 
import org.jfree.data.xy.XYSeries; 
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.ChartFactory; 
import org.jfree.chart.plot.PlotOrientation; 
import org.jfree.data.xy.XYSeriesCollection; 
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;



public class GraphTest {


    public JFreeChart runSimGraph(String chartTitle, String xLabel, String yLabel, boolean legend ,double[][] graphValues) {


        JFreeChart xylineChart = ChartFactory.createXYLineChart(
            chartTitle,
            xLabel,
            yLabel,
            createSimDataset(graphValues),
            PlotOrientation.VERTICAL,
            legend, false, false);
        final XYPlot plot = xylineChart.getXYPlot();

        //Axes (Domain - x , Range - y)
        NumberAxis domain = (NumberAxis) plot.getDomainAxis();
        domain.setRange(0,24);
        plot.setBackgroundPaint(new Color(240, 240, 240));
        XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer(false, true);
        //renderer.setBaseLinesVisible(false); // retira as linhas entre os pontos
        //renderer.setBaseShapesFilled(false); //apaga o centro das shapes
        //renderer.setBaseShapesVisible(false); //apaga as shapes
        Shape teste = new Rectangle2D.Double(-(1.2/2), -(1.2/2), 1.2, 1.2);
        renderer.setSeriesShape(0, teste);
        renderer.setSeriesPaint(0, Color.RED);
        //renderer.setSeriesStroke(0, new BasicStroke(1.0f));
        renderer.setSeriesShape(1, teste);
        renderer.setSeriesPaint(1, Color.BLUE);
        renderer.setSeriesShape(2, teste);
        renderer.setSeriesPaint(2, Color.GREEN);
        plot.setRenderer(renderer);

        return xylineChart;
    }

    private XYDataset createSimDataset(double[][] values) {

        double[] gridAr=values[0];
        double[] essAr=values[1];
        double[] availableEnergy=values[2];

        final XYSeries temp1 = new XYSeries("1");
        final XYSeries temp2 = new XYSeries("2");
        final XYSeries temp3 = new XYSeries("3");


        for (double i = 0; i < 1440; i++) {
            temp1.add(i / 60, gridAr[(int) i]);
            temp2.add(i/60, essAr[(int)i]);
            temp3.add(i/60, availableEnergy[(int) i]);
        }
        final XYSeriesCollection dataset = new XYSeriesCollection();
        dataset.addSeries(temp1);
        dataset.addSeries(temp2);
        dataset.addSeries(temp3);
        return dataset;
    }




}

提前致谢并对“长篇帖子”感到抱歉,

Nhekas

1 个答案:

答案 0 :(得分:2)

Swing是单线程的 - 在事件派发线程(EDT)上进行绘制和事件。从上面的评论中,您发布的循环在ActionListener内调用 - 这发生在EDT上,因此在EDT可以自由重绘之前不会发生对UI的更改(例如图表中的更改)(例如,之后的某个时间) actionPerformed方法结束)。

  

我想用不同的“刷新率”打印什么

如果您想以给定的费率刷新整个图表,我建议您使用javax.swing.Timer,根据需要更新图表。例如,以每秒一次的速率从JButton的ActionListener触发计时器:

ActionListener buttonListener = new ActionListener(){

    @Override
    public void actionPerformed(ActionEvent e) {

        javax.swing.Timer timer = new javax.swing.Timer(1000, new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent e) {
                //create the arrays
                chart1.setChart(chartTemp.runSimGraph("Title", "XLabel", "YLabel",true, new double[][]{Array1,Array2,Array3}));
            }

        });
        timer.start();
    }
};
myButton.addActionListener(buttonListener);

如果你想刷新一个可用点数的图表,考虑a)在自己的线程中执行计算,然后b)将点添加到XYSeries(在EDT上 - 这个而不是每次都重新创建数据集)。一个例子,改编自Adding points to XYSeries dynamically with JfreeChart

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.util.*;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import org.jfree.chart.*;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;


public class DynamicPlotAddition extends JFrame {

    private static final String title = "Dynamic Point Addition";
    private final Random rand = new Random();
    private XYSeries series = new XYSeries("Added");

    public DynamicPlotAddition(String s) {
        super(s);
        final ChartPanel chartPanel = createDemoPanel();
        this.add(chartPanel, BorderLayout.CENTER);
        Runnable runner = new Runnable(){

            @Override
            public void run() {
                int total = 1000;
                int iter = 0;
                while ( iter++ < total ){
                    SwingUtilities.invokeLater(new Runnable(){

                        @Override
                        public void run() {
                            series.add(rand.nextGaussian(), rand.nextGaussian());
                        }

                    });

                    try{Thread.sleep(100);}catch(Exception e){}
                }
            }

        };
        new Thread(runner).start();
    }

    private ChartPanel createDemoPanel() {
        JFreeChart jfreechart = ChartFactory.createScatterPlot(
            title, "X", "Y", createDataset(),
            PlotOrientation.VERTICAL, true, true, false);
        XYPlot xyPlot = (XYPlot) jfreechart.getPlot();
        xyPlot.setDomainCrosshairVisible(true);
        xyPlot.setRangeCrosshairVisible(true);
        XYItemRenderer renderer = xyPlot.getRenderer();
        renderer.setSeriesPaint(0, Color.blue);
        NumberAxis domain = (NumberAxis) xyPlot.getDomainAxis();
        domain.setVerticalTickLabels(true);
        return new ChartPanel(jfreechart);
    }

    private XYDataset createDataset() {
        XYSeriesCollection xySeriesCollection = new XYSeriesCollection();
        xySeriesCollection.addSeries(series);
        return xySeriesCollection;
    }

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                DynamicPlotAddition demo = new DynamicPlotAddition(title);
                demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                demo.pack();
                demo.setLocationRelativeTo(null);
                demo.setVisible(true);
            }
        });
    }
}

在发布的示例中,您从新线程调用simulateValues,并在生成每个点对时更新相应的系列