RealTime TimeSeriesChart freez Swing

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Post Reply
sashaspb09
Posts: 1
Joined: Thu Jan 21, 2021 7:21 am
antibot: No, of course not.

RealTime TimeSeriesChart freez Swing

Post by sashaspb09 » Thu Jan 21, 2021 11:36 am

Hello, I'm trying to create a project with displaying input data on TimeSeriesChart.
My programm gets data about every 600 milliseconds. I need add it to chart, I 'm using TimeSeriesCollection for adding Series(there would be about 33 Series) , XYItemRenderer - to hide/show Series and chart - ChartFactory.createTimeSeriesChart.
It's works great for 20 minutes,but after , programm starts get errors and freeze GUI, like when i try to zoom in chart,rectangle zone moves slower than mouse.
My question is ; how to build program logic to handle with that kind of issues. Like any example might be helpful,thanks in advice.
Here the sample,which get freeze after 10 min already, but this program might work for day or even longer,so it would lag even more.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package xdisplayjava.chart.tests;


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);
if (i == 30) {
s1 = new TimeSeries("Тemperature (" + num2 + ")");
}
if (i == 31) {
s1 = new TimeSeries("Pressure (" + num2 + ")");
}
if (i == 32) {
s1 = new TimeSeries("Humidity (" + num2 + ")");
}



seriesArray.addSeries(s1);
}
return seriesArray;
}

public MyDemoPanel() {
super(new BorderLayout());
final XYDataset dataset = this.createNumberedDataSet(33);
chart = this.createChart(dataset);
// renderer.setDefaultToolTipGenerator(new StandardXYToolTipGenerator("{0} ({1}, {2})", new SimpleDateFormat("yyyy"), new DecimalFormat("0.00")));
// ((DateAxis) (chart.getXYPlot().getDomainAxis())).setDateFormatOverride(new SimpleDateFormat("hh:mm:ss"));

// this.addChart(chart);
final ChartPanel chartPanel = new ChartPanel(chart);
boxPanel = new JPanel();
// boxPanel.setLayout(new BoxLayout(boxPanel, BoxLayout.Y_AXIS));

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);
if (i == 30) {
box1 = new JCheckBox("Тemperature (" + numchik + ")");
}
if (i == 31) {
box1 = new JCheckBox("Pressure (" + numchik + ")");
}
if (i == 32) {
box1 = new JCheckBox("Humidity (" + 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();
}
if (e.getActionCommand().equals("S1")) {
series = 0;
} else if (e.getActionCommand().equals("S2")) {
series = 1;
} else if (e.getActionCommand().equals("S3")) {
series = 2;
} else if (e.getActionCommand().equals("S4")) {
series = 3;
} else if (e.getActionCommand().equals("S5")) {
series = 4;
} else if (e.getActionCommand().equals("S6")) {
series = 5;
} else if (e.getActionCommand().equals("S7")) {
series = 6;
} else if (e.getActionCommand().equals("S8")) {
series = 7;
} else if (e.getActionCommand().equals("S9")) {
series = 8;}
else if (e.getActionCommand().equals("S10")){
series =9;}
else if (e.getActionCommand().equals("S11")){
series =10;}
else if (e.getActionCommand().equals("S12")){
series =11;}
else if (e.getActionCommand().equals("S13")){
series =12;}
else if (e.getActionCommand().equals("S14")){
series =13;}
else if (e.getActionCommand().equals("S15")){
series =14;}
else if (e.getActionCommand().equals("S16")){
series =15;}
else if (e.getActionCommand().equals("S17")){
series =16;}
else if (e.getActionCommand().equals("S18")){
series =17;}
else if (e.getActionCommand().equals("S19")){
series =18;}
else if (e.getActionCommand().equals("S20")){
series =19;}
else if (e.getActionCommand().equals("S21")){
series =20;}
else if (e.getActionCommand().equals("S22")){
series =21;}
else if (e.getActionCommand().equals("S23")){
series =22;}
else if (e.getActionCommand().equals("S24")){
series =23;}
else if (e.getActionCommand().equals("S25")){
series =24;}
else if (e.getActionCommand().equals("S26")){
series =25;}
else if (e.getActionCommand().equals("S27")){
series =26;}
else if (e.getActionCommand().equals("S28")){
series =27;}
else if (e.getActionCommand().equals("S29")){
series =28;}
else if (e.getActionCommand().equals("S30")){
series =29;}
else if (e.getActionCommand().equals("S31")){
series =30;}
else if (e.getActionCommand().equals("S32")){
series =31;}
else if (e.getActionCommand().equals("S33")){
series =32;}
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 = 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());




}
}
}
}

Post Reply