JFreeChart neu zeichnen sich Wenn Jtable sich ändert

Mohamed

Mitglied
Hallo Leute,
Ich bin gerade bei einemProjekt und dafür mus ich ein UI implementiere.
Problem:
Ich habe eine JTable die mir Daten anzeigt. Diese Jtable beinhalet zwei Column(Col1 für Zeit und Col2 für Werte von einem CO2 Sensor).
Am Amfang ist die
Mit einem click auf Start Button werde die Daten in der Tabelle mit einer Periode, die ich über den Konsole eingeben kann, hinzugefügt ,
Nach jeder Änderung in der Tabelle von der Koordianten x= Zeit und y=Co2 Werte, muss daraus ein LineChart dynamic dargestellt werden.

Wie kann ich diese Linechart Dynamic darstellen




ich habe versucht 7 Tage und Nächte das zu machen aber leider ohne Erfolg.


[FIELDSET=Code]public PanelGraphic() throws NotConnectedException {

initComponents();


}
private static JFreeChart createChart(final XYDataset dataset) {
JFreeChart chart = ChartFactory.createXYLineChart(
"KohlendioxdeTest", "Time ", "CO2 (ppm)", dataset,
PlotOrientation.VERTICAL, false, false, false);
return chart;
}
private void display(){

JFreeChart chart = createChart(dataset);
ChartPanel panel = new ChartPanel(chart);
final XYPlot plot = (XYPlot) chart.getPlot();
panel.setPreferredSize(new java.awt.Dimension(515, 265));
PlGraph.setLayout(new java.awt.BorderLayout());
PlGraph.add(panel, BorderLayout.CENTER);
PlGraph.validate();
}

private void jButtonStartActionPerformed(java.awt.event.ActionEvent evt) {



final DefaultTableModel model = (DefaultTableModel) tbCO2Value.getModel();

try {
if (!txtSetPeriode.getText().trim().isEmpty()) {

double peri = Long.parseLong(txtSetPeriode.getText());
co2.setCO2CallbackPeriod((long) peri * 1000);
co2.addCO2PPMListener(new BrickletCO2.PPmListener() {

@Override
public void PPmconverter(int kohlendioxide) {
model.addRow(new Object[]{DisplayTime.getTime(), String.valueOf(kohlendioxide)});
}
});
} else {
lbComment.setText("Bitte geben sie die Periode ein");
}


} catch (NotConnectedException ex) {
Logger.getLogger(PanelGraphic.class.getName()).log(Level.SEVERE, null, ex);
} catch (TimeoutException ex) {
Logger.getLogger(PanelGraphic.class.getName()).log(Level.SEVERE, null, ex);
}

tbCO2Value.getModel().addTableModelListener(new MyTableModelListener(tbCO2Value));
dataset = new XYSeriesCollection();


XYSeries series = new XYSeries("CO2 (ppm)");
int nRow = tbCO2Value.getRowCount();
int nCol = tbCO2Value.getColumnCount();
Object[][] tableData = new Object[nRow][nCol];
for (int i = 0; i < nRow; i++) {

tableData[0] = tbCO2Value.getValueAt(i, 0);
tableData[1] = tbCO2Value.getValueAt(i, 1);
// for (int i = 0; i < 10; i++) {
series.add((double) tableData[0],(double) tableData[1] );
}
dataset.addSeries(series);

display();

}
class MyTableModelListener implements TableModelListener {

JTable table;

private MyTableModelListener(JTable table) {
this.table = table;
}

@Override
public void tableChanged(TableModelEvent e) {

int firstRow = e.getFirstRow();
int lastRow = e.getLastRow();
int index = e.getColumn();

switch (e.getType()) {
case TableModelEvent.INSERT:
int nRow = tbCO2Value.getRowCount();
int nCol = tbCO2Value.getColumnCount();
Object[][] tableData = new Object[nRow][nCol];
for (int i = 0; i < nRow; i++) {

tableData[0] = tbCO2Value.getValueAt(i, 0);
tableData[1] = tbCO2Value.getValueAt(i, 1);


}



break;

}
}

}
} [/FIELDSET]
 

Anhänge

  • UserInterface.png
    UserInterface.png
    72,6 KB · Aufrufe: 39
  • UserInterface.jpg
    UserInterface.jpg
    76,7 KB · Aufrufe: 38
Zuletzt bearbeitet:
Sowohl JfreeChart als auch eine JTable verwenden das MVC-Konzept, d. h. es gibt eine Trennung zwischen Klassen mit Daten (Model) und Klassen zum Anzeigen (View). Du musst lediglich ein Objekt erstellen, welches als Model für sowohl einen JFreeChart als auch eine JTable dienen kann. In deinem Fall bedeutet das: ein Objekt, welches sowohl ein XYDataset als auch ein TableModel ist.
Um nicht beide Interfaces von Grund auf neu implementieren zu müssen, biten sich Wrapper an, die ein Interface über die Methoden des anderean ansprechbar machen. JFreeChart bietet selber einen solchen Wrapper an: die Klasse org.jfree.data.xy.XYDatasetTableModel. Sie benötigt eine Instanz von org.jfree.data.xy.TableXYDataset, die als Spezialisierung von XYDataset voraussetzt, daß alle Datenpunkte mit gleichem Index einen identischen x-Wert haben. Eine Implementierung von TableXYDataset für eine zweispaltige Tabelle, bei der man nachträglich noch Punkte anfügen kann, ist nicht besonders schwierig:
Java:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.ArrayList;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.Range;
import org.jfree.data.xy.AbstractXYDataset;
import org.jfree.data.xy.TableXYDataset;
import org.jfree.data.xy.XYDatasetTableModel;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;

public class TableAndChart {

    public static void main(String[] args) {
        JFrame frame = new JFrame("Table and Chart");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        PointList dataset = new PointList("Daten");
        ValueAxis xAxis = new NumberAxis("x");
        ValueAxis yAxis = new NumberAxis("y");
        xAxis.setRange(new Range(0, 500));
        yAxis.setRange(new Range(0, 500));
        xAxis.setAutoRange(false);
        yAxis.setAutoRange(false);
        XYPlot plot = new XYPlot(dataset, xAxis, yAxis, new XYLineAndShapeRenderer());
        JFreeChart chart = new JFreeChart(plot);
        frame.getContentPane().add(new ChartPanel(chart));
        JTable table = new JTable(new XYDatasetTableModel(dataset));
        JScrollPane scroll = new JScrollPane();
        scroll.getViewport().setPreferredSize(new Dimension(160, 500));
        scroll.setViewportView(table);
        frame.getContentPane().add(scroll, BorderLayout.EAST);
        frame.pack();
        frame.setVisible(true);
        for (int i = 0; i < 500; i++) {
            try {
                Thread.sleep(20);
            } catch (InterruptedException ie) {
            }
            dataset.addPoint(i, i);

        }
    }

    static class PointList extends AbstractXYDataset implements TableXYDataset {

        private ArrayList<Double[]> points = new ArrayList<Double[]>();
        private Comparable key;

        public PointList(Comparable key) {
            this.key = key;
        }

        public Comparable getSeriesKey(int index) {
            return key;
        }

        public int getSeriesCount() {
            return 1;
        }

        public int getItemCount(int series) {
            return points.size();
        }

        public int getItemCount() {
            return points.size();
        }

        @Override
        public double getXValue(int series, int item) {
            return points.get(item)[0].doubleValue();
        }

        @Override
        public double getYValue(int series, int item) {
            return points.get(item)[1].doubleValue();
        }

        public Number getX(int series, int item) {
            return points.get(item)[0];
        }

        public Number getY(int series, int item) {
            return points.get(item)[1];
        }

        public void addPoint(double x, double y) {
            points.add(new Double[]{new Double(x), new Double(y)});
            fireDatasetChanged();
        }
    }
}
 
Zuletzt bearbeitet:
habe ich versucht mit dem oben geposteten Code weiterzuarbeiten damit ich weiterkomme kann , aber das Problem passiert nicht und in der Tabelle wird nur ein Row angezeigt und bricht das Code ab.

Geänderter Code;
Java:
private void jButtonStartActionPerformed(java.awt.event.ActionEvent evt) {                                             

        final DefaultTableModel model = (DefaultTableModel) tbCO2Value.getModel();

        final PointList dataset = new PointList("Daten");
        ValueAxis xAxis = new NumberAxis("x");
        xAxis.setAutoRange(true);
        xAxis.setFixedAutoRange(6000.0);

        ValueAxis yAxis = new NumberAxis("y");
        yAxis.setRange(0.0, 1500.0);
        XYPlot plot = new XYPlot(dataset, xAxis, yAxis, new XYLineAndShapeRenderer());
        JFreeChart chart = new JFreeChart(plot);
        ChartPanel panel = new ChartPanel(chart);

        panel.setPreferredSize(new java.awt.Dimension(515, 265));
        XYDatasetTableModel tbCO2Value = new XYDatasetTableModel(dataset);
        JTable table = new JTable(tbCO2Value);
        PlGraph.setLayout(new java.awt.BorderLayout());
        PlGraph.add(panel, BorderLayout.CENTER);
        PlGraph.validate();

try {
                co2.setCO2CallbackPeriod(peri * 1000);
            } catch (NotConnectedException | TimeoutException ex) {
                Logger.getLogger(PanelGraphic.class.getName()).log(Level.SEVERE, null, ex);
            }
            if (listener == null) {
                listener = new BrickletCO2.PPmListener() {

                    @Override
                    public void PPmconverter(int kohlendioxide) {

                        model.addRow(new Object[]{DisplayTime.getTime(), String.valueOf(kohlendioxide)});

                        System.out.println(" Time ist -> " + DisplayTime.getTime() + " co2 beträgt :" + String.valueOf(kohlendioxide));

                     double time = Double.parseDouble(DisplayTime.getTime());
                   dataset.addPoint(time, (double) kohlendioxide);
                  
                      
                    }
                };

                co2.addCO2PPMListener(listener);
            }
}

hier sit die angezeigte Fehlermeldung

run:
Exception in thread "Callback-Processor" java.lang.NumberFormatException: For input string: "12:30:43"
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2043)
at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
at java.lang.Double.parseDouble(Double.java:538)
at MyFrames.Panels.PanelGraphic$6.PPmconverter(PanelGraphic.java:333)

Time ist -> 12:30:43 co2 beträgt :1374




die Zeile PanelGraphic.java:333 weist darauf hin ->

double time = Double.parseDouble(DisplayTime.getTime());
dataset.addPoint(time , (double) kohlendioxide);
 
Zuletzt bearbeitet:
Bei dem String "12:30:43" handelt es sich offenbar um eine Zeitangabe. Diese kann natürlich nicht direkt in einen double-Wert umgewandelt werden.
Du musst offenbar ein SimpleDateFormat verwenden:
Java:
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
double value = sdf.parse(DisplayTime.getTime()).getTime();
Ausserdem rate ich nochmals dazu, die Trennung zwischen dem XYDataset und dem TableModel aufzuheben. Dadurch vermeidest du doppelte Datenhaltung und musst dich nicht mehr um die Synchronisation kümmern.,
 
Zuletzt bearbeitet:
Danke Harry für deine Hilfe.

Diese Double value variable gibt die Zeit als double Wert zurück und nicht das Format die ich eingegeben habe und die ich bauche ("HH:mm:ss").
wie kann ich machen dass trotz die value-Variable als double ist, dass er dieses Format ("HH:mm:ss") anzeigt.
Das Problem liegt in dieser Methode dass alle Variable als double deklarieret sind

Java:
public void addPoint(Double x, Double y) {
            points.add(new Double[]{new Double(x), new Double(y)});
            fireDatasetChanged();
        }
 
Zuletzt bearbeitet:
Ich sehe da zwei grundsätzliche Möglichkeiten:
1. Du speicherst wie bisher die Zeitangaben als double (oder Double) und wandelst sie mit einem geeigneten TableCellRenderer in einen String mit dem gewünschten Format um.
2. Du speicherst die Zeitangaben als String und wandelst sie in der getX()-Methode aus der PointList in eine Zahl um.
 

Zurück
Oben