我正在使用不同的“刷新率”绘制我要打印的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
答案 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
,并在生成每个点对时更新相应的系列