Solución:
Si su variable se actualiza tan rápido, no tiene sentido actualizar un gráfico cada vez.
¿Ha pensado en almacenar en búfer los cambios de variable y actualizar el gráfico en un hilo diferente, digamos, cada 5 segundos? Debería encontrar que JFreeChart puede manejar bien tales tasas de actualización.
Dado que JFreeChart es una biblioteca de escritorio normal, puede integrarla con una aplicación estándar de Swing muy fácilmente. O bien, puede usarlo para crear gráficos a través de una aplicación web (renderizándolo en un JPEG / PNG, etc. JFreeChart también puede generar mapas de imágenes automáticamente, por lo que puede usar el mouse, etc.)
Para que su CPU esté muy por debajo del 100% y permitir que su GUI siga respondiendo, debe reducir la velocidad de actualización de su gráfico. Una tasa de actualización máxima de alrededor de 24 cuadros por segundo tiene sentido para un gráfico en tiempo real; cualquiera más rápido es más o menos indistinguible de todos modos. Si sus datos llegan más rápido que esa tasa, solo necesita almacenarlos en un búfer en segundo plano y actualizar su gráfico en primer plano a la tasa de actualización deseada. En el siguiente ejemplo, utilizo XChart junto con un SwingWorker
hilo de fondo. La captura de datos se simula a una velocidad de una por cada 5 ms y el gráfico se actualiza a 24 fotogramas por segundo. Este concepto debería funcionar con JFreeCharts o cualquier otra biblioteca de gráficos también con una ligera modificación. Descargo de responsabilidad: soy el desarrollador principal de XChart.
import java.util.LinkedList;
import java.util.List;
import javax.swing.SwingWorker;
import org.knowm.xchart.QuickChart;
import org.knowm.xchart.SwingWrapper;
import org.knowm.xchart.XYChart;
/**
* Creates a real-time chart using SwingWorker
*/
public class SwingWorkerRealTime {
MySwingWorker mySwingWorker;
SwingWrapper<XYChart> sw;
XYChart chart;
public static void main(String[] args) throws Exception {
SwingWorkerRealTime swingWorkerRealTime = new SwingWorkerRealTime();
swingWorkerRealTime.go();
}
private void go() {
// Create Chart
chart = QuickChart.getChart("SwingWorker XChart Real-time Demo", "Time", "Value", "randomWalk", new double[] { 0 }, new double[] { 0 });
chart.getStyler().setLegendVisible(false);
chart.getStyler().setXAxisTicksVisible(false);
// Show it
sw = new SwingWrapper<XYChart>(chart);
sw.displayChart();
mySwingWorker = new MySwingWorker();
mySwingWorker.execute();
}
private class MySwingWorker extends SwingWorker<Boolean, double[]> {
LinkedList<Double> fifo = new LinkedList<Double>();
public MySwingWorker() {
fifo.add(0.0);
}
@Override
protected Boolean doInBackground() throws Exception {
while (!isCancelled()) {
fifo.add(fifo.get(fifo.size() - 1) + Math.random() - .5);
if (fifo.size() > 500) {
fifo.removeFirst();
}
double[] array = new double[fifo.size()];
for (int i = 0; i < fifo.size(); i++) {
array[i] = fifo.get(i);
}
publish(array);
try {
Thread.sleep(5);
} catch (InterruptedException e) {
// eat it. caught when interrupt is called
System.out.println("MySwingWorker shut down.");
}
}
return true;
}
@Override
protected void process(List<double[]> chunks) {
System.out.println("number of chunks: " + chunks.size());
double[] mostRecentDataSet = chunks.get(chunks.size() - 1);
chart.updateXYSeries("randomWalk", null, mostRecentDataSet, null);
sw.repaintChart();
long start = System.currentTimeMillis();
long duration = System.currentTimeMillis() - start;
try {
Thread.sleep(40 - duration); // 40 ms ==> 25fps
// Thread.sleep(400 - duration); // 40 ms ==> 2.5fps
} catch (InterruptedException e) {
}
}
}
}