I'm writing a program which would display incoming data while day. It's getting data about every 600 milliseconds and adding it to the TimeSeries Chart. The problem is: after about 10 minutes of work, GUI starts freezing. But if display only few series of 33 it's become fine. So maybe I am doing something wrong?
How to solve that freezing? My SwingWorker
may be weak, or chosen JFreeChart collection.
Any tips might be helpful, thank you!
My short code example:
import java.awt.event.ActionEvent;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.ChartFactory;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.data.xy.XYSeries;
import org.jfree.chart.JFreeChart;
import org.jfree.data.xy.XYDataset;
import java.awt.Dimension;
import java.awt.Component;
import javax.swing.JCheckBox;
import org.jfree.chart.ChartPanel;
import java.awt.LayoutManager;
import java.awt.BorderLayout;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import java.awt.event.ActionListener;
import java.awt.Window;
import org.jfree.chart.ui.UIUtils;
import javax.swing.JPanel;
import java.awt.Container;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Paint;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JSeparator;
import javax.swing.SwingWorker;
import org.jfree.chart.title.LegendTitle;
import org.jfree.chart.ui.ApplicationFrame;
import org.jfree.data.time.Millisecond;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
public class HideSeriesDemo1 extends ApplicationFrame {
public HideSeriesDemo1(final String title) {
super(title);
this.setContentPane(new MyDemoPanel());
}
public static JPanel createDemoPanel() {
return new MyDemoPanel();
}
public static void main(final String[] args) {
final HideSeriesDemo1 demo = new HideSeriesDemo1("JFreeChart: HideSeriesDemo1.java");
demo.pack();
UIUtils.centerFrameOnScreen(demo);
demo.setVisible(true);
}
static class MyDemoPanel extends JPanel implements ActionListener {
final JFreeChart chart;
private JPanel boxPanel;
TimeSeriesCollection seriesArray;
private XYItemRenderer renderer;
private void setLinesVisible() {
for (int i = 0; i < seriesArray.getSeriesCount(); i++) {
renderer.setSeriesVisible(i, true);
JCheckBox box = (JCheckBox) boxPanel.getComponent(i);
box.setSelected(true);
}
}
private void setLinesInvisible() {
for (int i = 0; i < seriesArray.getSeriesCount(); i++) {
renderer.setSeriesVisible(i, false);
JCheckBox box = (JCheckBox) boxPanel.getComponent(i);
box.setSelected(false);
}
}
private XYDataset createNumberedDataSet(int num) {
seriesArray = new TimeSeriesCollection();
for (int i = 0; i < num; i++) {
int num2 = i + 1;
TimeSeries s1 = new TimeSeries("Channel №" + num2);
seriesArray.addSeries(s1);
}
return seriesArray;
}
public MyDemoPanel() {
super(new BorderLayout());
final XYDataset dataset = this.createNumberedDataSet(33);
chart = this.createChart(dataset);
final ChartPanel chartPanel = new ChartPanel(chart);
boxPanel = new JPanel();
boxPanel.setLayout(new GridLayout(0, 11));
boxPanel.validate();
for (int i = 0; i < 33; i++) {
int numchik = i + 1;
JCheckBox box1 = new JCheckBox("Channel №" + numchik);
String com = "S" + numchik;
box1.setSelected(true);
box1.setActionCommand(com);
box1.addActionListener(this);
boxPanel.add(box1);
}
boxPanel.validate();
final JButton btn = new JButton("All not sellected");
btn.setVisible(true);
btn.setActionCommand("btn");
btn.addActionListener(this);
boxPanel.add(btn);
final JButton btn2 = new JButton("All sellected");
btn2.setVisible(true);
btn2.setActionCommand("btn2");
btn2.addActionListener(this);
boxPanel.add(btn2);
final JButton btn3 = new JButton("SwingWorker?");
btn3.setVisible(true);
btn3.setActionCommand("btn3");
btn3.addActionListener(this);
boxPanel.add(btn3);
this.add(chartPanel);
this.add(boxPanel, "South");
JPopupMenu pop = chartPanel.getPopupMenu();
pop.add(new JSeparator());
JMenuItem remBtn = new JMenuItem("All not selected");
remBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
setLinesInvisible();
}
});
pop.add(remBtn);
JMenuItem addBtn = new JMenuItem("All visible");
addBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
setLinesVisible();
}
});
pop.add(addBtn);
}
private JFreeChart createChart(final XYDataset dataset) {
final JFreeChart chart = ChartFactory.createTimeSeriesChart("xDisplay", "Time", "Data", dataset, true, true, false);
final XYPlot plot = (XYPlot) chart.getPlot();
this.renderer = plot.getRenderer();
return chart;
}
@Override
public void actionPerformed(final ActionEvent e) {
int series = -1;
if (e.getActionCommand().equals("btn")) {
this.setLinesInvisible();
System.out.println("set invisible btn pressed");
boxPanel.validate();
// System.out.println("btn pressed");
return;
}
if (e.getActionCommand().equals("btn2")) {
setLinesVisible();
boxPanel.validate();
System.out.println("setBtnVisible pressed");
return;
}
if (e.getActionCommand().equals("btn3")) {
System.out.println("swingworker");
MySwingWorker swi = new MySwingWorker();
swi.execute();
}
for (int i = 0; i<33;i++){
String s="S"+i;
if (e.getActionCommand().equals(s)) {
series = i-1;
}
}
if (series >= 0) {
final boolean visible = this.renderer.getItemVisible(series, 0);
this.renderer.setSeriesVisible(series, !visible);
}
}
private class MySwingWorker extends SwingWorker<Boolean, double[]> {
LinkedList<Double> fifo = new LinkedList<Double>();
public MySwingWorker() {
fifo.add(0.0);
}
@Override
protected Boolean doInBackground() {
while (!isCancelled()) {
try {
Thread.sleep(600);
} catch (InterruptedException ex) {
Logger.getLogger(HideSeriesDemo1.class.getName()).log(Level.SEVERE, null, ex);
}
fifo.add(fifo.get(fifo.size() - 1) + Math.random() - .5);
if (fifo.size() > 1000) {
fifo.removeFirst();
}
double[] array = new double[fifo.size()];
for (int i = 0; i < fifo.size(); i++) {
array[i] = fifo.get(i);
}
System.out.println(array.length + " : " + Arrays.toString(array) + "Array: ");
publish(array);
try {
Thread.sleep(5);
} catch (InterruptedException e) {
// eat it. caught when interrupt is called
System.out.println("MySwingWorker shut down." + " name:" + Thread.currentThread().getName());
}
}
return true;
}
@Override
protected void process(List<double[]> chunks) {
double[] mostRecentDataSet = chunks.get(chunks.size() - 1);
for (int i = 0; i < seriesArray.getSeriesCount(); i++) {
TimeSeries series = seriesArray.getSeries(i);
series.addOrUpdate(new Millisecond(), mostRecentDataSet[0] + i);
}
fifo.removeFirst();
System.out.println(" repaint zone " + " name:" + Thread.currentThread().getName());
}
}
}
}