Code: Select all
package sat;
import java.util.Random;
import javax.swing.JFrame;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PiePlot3D;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
import org.jfree.data.general.DatasetGroup;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.general.PieDataset;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
public class ChartFrame extends JFrame {
private static final int MAX_ITERATION = 1000;
private static final int SLEEP_TIME = 100;
private XYSeries minFitSerie;
private XYSeries avgFitSerie;
private XYSeries maxFitSerie;
private int N = 50;
private double[] minFitVal = new double[N];
private double[] maxFitVal = new double[N];
private double[] avgFitVal = new double[N];
private Random rand = new Random();
private Algorithm alg;
public ChartFrame() {
super("Chart");
setSize(1024, 768);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().add(makeChart());
setVisible(true);
alg = new Algorithm();
alg.initAlgorithm();
run();
}
public void run() {
for(int i = 0; i < MAX_ITERATION; i++) {
alg.runIteration();
updateSeries();
try {
Thread.sleep(SLEEP_TIME);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
repaint();
}
}
private void updateSeries() {
minFitSerie.clear();
maxFitSerie.clear();
avgFitSerie.clear();
for(int i = 0; i < N - 1; i++) {
minFitVal[i] = minFitVal[i+1];
maxFitVal[i] = maxFitVal[i+1];
avgFitVal[i] = avgFitVal[i+1];
minFitSerie.add(i, minFitVal[i]);
maxFitSerie.add(i, maxFitVal[i]);
avgFitSerie.add(i, avgFitVal[i]);
}
int i = N - 1;
double v1 = alg.getCurrentMinFitness();
double v2 = alg.getCurrentMaxFitness();
double v3 = alg.getCurrentAvgFitness();
minFitVal[i] = v1;
maxFitVal[i] = v2;
avgFitVal[i] = v3;
minFitSerie.add(i, minFitVal[i]);
maxFitSerie.add(i, maxFitVal[i]);
avgFitSerie.add(i, avgFitVal[i]);
}
ChartPanel makeChart() {
minFitSerie = new XYSeries("min");
maxFitSerie = new XYSeries("max");
avgFitSerie = new XYSeries("avg");
XYDataset xyDatasetMin = new XYSeriesCollection(minFitSerie);
XYDataset xyDatasetMax = new XYSeriesCollection(maxFitSerie);
XYDataset xyDatasetAvg = new XYSeriesCollection(avgFitSerie);
JFreeChart chart = ChartFactory.createXYLineChart("Population overview", "Pupulation number", "Fitness",
null, PlotOrientation.VERTICAL, true, true, false);
XYPlot plot = chart.getXYPlot();
plot.setDataset(0, xyDatasetMin);
plot.setRenderer(0, new StandardXYItemRenderer());
plot.setDataset(1, xyDatasetMax);
plot.setRenderer(1, new StandardXYItemRenderer());
plot.setDataset(2, xyDatasetAvg);
plot.setRenderer(2, new StandardXYItemRenderer());
return new ChartPanel(chart);
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ChartFrame frame = new ChartFrame();
}
}
Firtst fundamental question: did i use correct type of chart, did process of creating, and updating values, redrawing is correct ? I doubt because i have got exception after about 60 iterations and it repeats with period about 50-70 iterations.
Code: Select all
Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Index: 47, Size: 0 // Index value in each exception repetition differs
at java.util.ArrayList.RangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at org.jfree.data.xy.XYSeries.getDataItem(XYSeries.java:616)
at org.jfree.data.xy.XYSeriesCollection.getX(XYSeriesCollection.java:320)
at org.jfree.data.xy.AbstractXYDataset.getXValue(AbstractXYDataset.java:75)
at org.jfree.chart.renderer.RendererUtilities.findLiveItemsUpperBound(RendererUtilities.java:181)
at org.jfree.chart.renderer.RendererUtilities.findLiveItems(RendererUtilities.java:262)
at org.jfree.chart.plot.XYPlot.render(XYPlot.java:3729)
at org.jfree.chart.plot.XYPlot.draw(XYPlot.java:3310)
at org.jfree.chart.JFreeChart.draw(JFreeChart.java:1235)
at org.jfree.chart.ChartPanel.paintComponent(ChartPanel.java:1668)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintToOffscreen(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
at javax.swing.BufferStrategyPaintManager.paint(Unknown Source)
at javax.swing.RepaintManager.paint(Unknown Source)
at javax.swing.JComponent._paintImmediately(Unknown Source)
at javax.swing.JComponent.paintImmediately(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.seqPaintDirtyRegions(Unknown Source)
at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Next thing i want to change are values on y axis. I know a priori that values are from certain interval <a, b>, and let's say that a = 180, b = 200. And now on Y axis i have values: 0, 10, 20, 30, ... 200. It causes that curves are almost on the top of the screen. So i would like have change to customize Y values and for this example they should be sth like that: 0, 50, 100, 150, 200, 250, 300;
I would appreciate if some one show me general idea how to do such plotting in most efficient way and without errors in rendering.
Edit. Here is working code(previous one required class with algorithm), you can try it and will see problems i described above. So it would be sufficient for me if one improves this code (what i really care is to how to get rid of blinking, changing axis, and background lines, these are not static now).
Code: Select all
import java.util.Random;
import javax.swing.JFrame;
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.chart.renderer.xy.StandardXYItemRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
public class ChartFrame extends JFrame {
private static final int MAX_ITERATION = 100000000;
private static final int FPS = 25;
private final int REFRESH_RATE = 1000/FPS;
private XYSeries minFitSerie;
private XYSeries avgFitSerie;
private XYSeries maxFitSerie;
private int N = 50;
private double[] minFitVal = new double[N];
private double[] maxFitVal = new double[N];
private double[] avgFitVal = new double[N];
private long lastTime;
private Random rand = new Random();
public ChartFrame() {
super("Chart");
setSize(1024, 768);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().add(makeChart());
setVisible(true);
lastTime = System.nanoTime();
run();
}
public void run() {
for(int i = 0; i < MAX_ITERATION; i++) {
//alg.runIteration(); here complex calculations
generateSeries();
long currentTime = System.nanoTime();
long elapsed = currentTime - lastTime;
elapsed /= 1000000;
if(elapsed < REFRESH_RATE) continue;
lastTime = currentTime;
repaint();
}
}
private void generateSeries() {
minFitSerie.clear();
maxFitSerie.clear();
avgFitSerie.clear();
for(int i = 0; i < N - 1; i++) {
minFitVal[i] = minFitVal[i+1];
maxFitVal[i] = maxFitVal[i+1];
avgFitVal[i] = avgFitVal[i+1];
minFitSerie.add(i, minFitVal[i]);
maxFitSerie.add(i, maxFitVal[i]);
avgFitSerie.add(i, avgFitVal[i]);
}
int i = N - 1;
double v1 = rand.nextDouble()*10 + 180;
double v2 = rand.nextDouble()*10 + 190;
double v3 = (v1 + v2)/2;
minFitVal[i] = v1;
maxFitVal[i] = v2;
avgFitVal[i] = v3;
minFitSerie.add(i, minFitVal[i]);
maxFitSerie.add(i, maxFitVal[i]);
avgFitSerie.add(i, avgFitVal[i]);
}
ChartPanel makeChart() {
minFitSerie = new XYSeries("min");
maxFitSerie = new XYSeries("max");
avgFitSerie = new XYSeries("avg");
XYDataset xyDatasetMin = new XYSeriesCollection(minFitSerie);
XYDataset xyDatasetMax = new XYSeriesCollection(maxFitSerie);
XYDataset xyDatasetAvg = new XYSeriesCollection(avgFitSerie);
JFreeChart chart = ChartFactory.createXYLineChart("Population overview", "Population number", "Fitness",
null, PlotOrientation.VERTICAL, true, true, false);
chart.setBackgroundImageAlpha(0.1f);
XYPlot plot = chart.getXYPlot();
plot.setDataset(0, xyDatasetMin);
plot.setRenderer(0, new StandardXYItemRenderer());
plot.setDataset(1, xyDatasetMax);
plot.setRenderer(1, new StandardXYItemRenderer());
plot.setDataset(2, xyDatasetAvg);
plot.setRenderer(2, new StandardXYItemRenderer());
return new ChartPanel(chart);
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ChartFrame frame = new ChartFrame();
}
}