Page 1 of 1

Gráfica en tiempo real

Posted: Fri Apr 27, 2007 10:23 am
by 7663010
Hola,

Queremos utilizar la gráfica en tiempo real, ir recibiendo datos y mostrandolos, unas 4 veces por segundo (si pudiera ser continuo mucho mejor). He utilizado las 'FastLines', no pinta todos los puntos (setDrawAllPoints(false)), no se autorepinta (setAutoRepaint(false)), recuerdo haber viso en un articulo vuestro algo del FastPen (o algo asi), pero no encuentro el articulo y no se que mas cosas hacer.

El hecho es que con una gráfica funcionando, a 4 'pintadas' por segundo, consume demasiado, con 3 o 4 series y viendo 'bastante' grafica en pantalla, chupa un 70-80% de CPU.

Pregunta: Me podeis pasar el link de vuestro articulo?, me podeis aconsejar que hacer para conseguir el mejor rendimiento?, en este caso, no necesito grandes virguerias, simplemente mostrar los puntos y hacer zooms (cuando se congele la grafica), no necesitamos ninguna tool, ni nada en 3d ni nada por el estilo, solo pintar fluidamente, con el menor consumo posible.

Gracias

Carlos.

Posted: Wed May 02, 2007 10:50 am
by narcis
Hola Carlos,

El articulo esta aquí, en nuestras FAQ.

Espero que esto te ayude, si sigues teniendo problemas no dudes en preguntarlo.

Posted: Fri May 04, 2007 10:34 am
by 7663010
Hola,

Estoy siguiendo el articulo (mas o menos) pero tengo algunos problemas.

Nueva grafica:

Code: Select all

tChart.setBackground(new Color(238, 238, 238));
tChart.getPanel().setBevelWidth(0);
tChart.setText("");
tChart.getLegend().setTopLeftPos(0);
tChart.getLegend().setMaxNumRows(3);
        
tChart.setAutoRepaint(autoRepaint);
tChart.getChart().getAspect().setView3D(false);
        
tChart.getLegend().setAlignment(LegendAlignment.BOTTOM);
tChart.getLegend().setLegendStyle(LegendStyle.SERIES);
tChart.getAxes().getCustom().removeAll();
tChart.getPanel().setMarginUnits(PanelMarginUnits.PIXELS);
tChart.addChartListener(this);
tChart.addChartPaintListener(this);
        
tChart.getPanning().setAllow(ScrollMode.NONE);
Al añadir una serie

Code: Select all

novaSerie=new FastLine();
((FastLine)novaSerie).setDrawAllPoints(false);
((FastLine)novaSerie).setAutoRepaint(false);
...
novaSerie.getXValues().setOrder(ValueListOrder.NONE);
...
novaSerie.addSeriesPaintListener(this);

Axis axis=tChart.getAxes().getCustom().getNew();
axis.getAxisPen().setColor(color);
axis.getLabels().setColor(color);
axis.getMinorGrid().setVisible(false);
axis.getMinorTicks().setColor(color);
axis.getTicks().setColor(color);
axis.getTicksInner().setColor(color);
        
axis.setAutomatic(true);
        
axis.setVisible(false);
        
tChart.getAxes().getCustom().add(axis);
//associem els axis amb les sèries:
novaSerie.setCustomVertAxis(axis);
        
//afegim les sèries al TChart:
tChart.addSeries(novaSerie);
Lo que hay en medio simplemente es para seleccionar el color de la serie y de los axis. La propiedad FastPen no esta implementada en Java, tampoco esta implementada la funcion FastCalc de los axis.

El problema viene al añadir puntos, si los añado uno a uno, pinta correctamente, pero consume mucha cpu y va bastante lento, con unos 5000 puntos en la pantalla (como mucho).
Añadimos puntos 4 veces por segundo, y cada vez se añaden unos 250 puntos, tal vez algunos mas, por lo que una vez añadidos estos puntos, borramos de golpe los sobrantes, por ejemplo, con 5000 puntos en pantalla, y añadidos 270, pues borramos los primeros 270 de golpe.
Pero sigue sin funcionar correctamente, va lento y carga mucho el sistema con una sola grafica en la pantalla.
Queria probar a introducir los numeros en las serie directamente desde un ArrayList, montar yo este array, y cuando este completo pasarlo directamente a la serie, pero entonces saltan excepciones:

Code: Select all

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
        at com.steema.teechart.styles.ValueList.calcStats(ValueList.java:307)
        at com.steema.teechart.styles.ValueList.getMaximum(ValueList.java:357)
        at com.steema.teechart.styles.Series.getMaxXValue(Series.java:3692)
        at com.steema.teechart.Chart.internalMinMax(Chart.java:1583)
        at com.steema.teechart.axis.Axis.calcMinMax(Axis.java:1116)
        at com.steema.teechart.axis.Axis.adjustMaxMin(Axis.java:355)
        at com.steema.teechart.axis.Axes.adjustMaxMin(Axes.java:216)
        at com.steema.teechart.Chart.calcAxisRect(Chart.java:1923)
        at com.steema.teechart.Chart.internalDraw(Chart.java:630)
        at com.steema.teechart.Chart.paint(Chart.java:1807)
        at com.steema.teechart.TChart.paintComponent(TChart.java:568)
        at javax.swing.JComponent.paint(JComponent.java:1005)
        at javax.swing.JComponent.paintWithOffscreenBuffer(JComponent.java:4963)
        at javax.swing.JComponent.paintDoubleBuffered(JComponent.java:4916)
        at javax.swing.JComponent._paintImmediately(JComponent.java:4859)
        at javax.swing.JComponent.paintImmediately(JComponent.java:4666)
        at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:451)
        at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(SystemEventQueueUtilities.java:114)
        at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:461)
        at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:242)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:163)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:157)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:149)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)
El codigo es este:

Code: Select all

private void afegirDadesGraficaTemps(double[] bufferDades, int numBlocs,
            int tamanyBlocDades, int intervalEntreBlocsAPintar, boolean repintarGrafica)
    {
        //per a cada s�rie:
        for (int i=0; i<numBlocs; i+=intervalEntreBlocsAPintar) {
            //per a cada bloc:
            for(int j=0; j<tamanyBlocDades-2; j++) {
                if (graficaTemps.isSerieVisible(j)) {
                    arraysDadesX[j].add(bufferDades[i*tamanyBlocDades + 1]);
                    arraysDadesY[j].add(bufferDades[i*tamanyBlocDades + j + 2]);
                    
                }
            }
            for (int k = 0; k < graficaTemps.getNumSeries(); k++) {
                if (graficaTemps.isSerieVisible(k)) { 
                    graficaTemps.afegirValor(arraysDadesX[k], arraysDadesY[k], k);
                }
            }
        }
        
        if (repintarGrafica)
            graficaTemps.updateAllSeriesVisibles();
    }

Code: Select all

public void updateAllSeriesVisibles() {
        if (maxItemCount!=null) {
            for (int i=0; i<tChart.getSeriesCount(); i++) {
                //esborrem de cop i per cada sèrie els punts sobrants segons el màxim de punts establert:
                if (numsActualsPuntsSeries.get(i) > maxItemCount) {
                    tChart.getSeries(i).delete(0, numsActualsPuntsSeries.get(i)-maxItemCount);
                    //tChart.getSeries(i).delete(0);
                    numsActualsPuntsSeries.set(i, maxItemCount);
                }
            }
        }
        
//        tChart.repaint();
    }
Alguna idea de que puedo hacer para que no sucedan estas excepciones?, me he dejado alguna cosa para que la grafica vaya mas fluida y consuma menos recursos?

Gracias

Carlos.

Posted: Fri May 04, 2007 10:44 am
by narcis
Hola Carlos,

En la demo TeeChart.Features.jar hay un ejemplo de como añadir datos a una serie utilizando arrays. El ejemplo está en All Features\Welcome!\Chart Styles\Standard\Fast Line\FastLine Speed. Puedes ver el código del ejemplo en la pestaña Source Code.

Puedes provar si funciona bien añadiendo los valores a la serie como en el ejemplo.

Posted: Mon May 07, 2007 9:31 am
by 7663010
En ese ejemplo lo que hace es poner directamente un array como serie (una vez creado este array), yo que lo quiero hacer es ur añadiendo arrays a otro ya existente, el de la serie, igual que se borran de golpe sub-arrays de la serie, quiero añadir un sub-array a la misma, pero da las excepciones que ponia arriba.

El resto esta igual (preparado para mi aplicacion claro), pero no es el ejemplo exacto.

Carlos.

Posted: Mon May 07, 2007 9:40 am
by narcis
Hola Carlos,

Cuando se añade un array a una serie se sustituyen los datos existentes por los del array. En este caso, antes de añadir un segundo array a la serie tendras que concatenar los 2 arrays manualmente y añadir el resultante a la serie.

Posted: Mon May 07, 2007 11:30 am
by 7663010
Al final no hemos utilizado la de arrays, sino que se lo volvemos a poner directamente con puntos.

He estado 'afinando' los tiempos de repintar y tal, y ahora parece que funciona (y muy bien claro :D ), a 1khz de adquisicion, y pintando puntos 4 veces por segundo, con 22 segundos en la pantalla a la vez, dos series dibujandose y una grafica que tal vez ocupe 1/5 de la pantalla, el consumo ronda el 45-50% sin ningun problema, estas pruebas ademas en un servidor ltsp con muchas cosas mas corriendo.

Gracias

Carlos.