Ceci est ma première publication sur StackOverFlow alors s'il vous plaît excuser les erreurs dans mon message. Venir au sujet J'ai un programme qui est censé tracer certaines coordonnées X et Y. J'utilise actuellement JFREECHART pour XYChart. Afin de répondre aux exigences de mise à jour à haute vitesse, j'ai 2 séries. Series1 accumule 1000 points de données, puis est ajouté au graphique pour l'afficher.Après cette série2 accumaltes 1000 points de données et une fois qu'il est finis efface series1 (pour le préparer pour 1000 nouveaux points de données) et attache série2 au graphique (qui a maintenant 1000 points de données) ... et ce cycle continue. Le problème est lié aux fonctions XYSeries.clear et XYSeries.add. Apparemment, ils créent leurs propres threads et avant qu'ils puissent terminer l'exécution, je génère déjà un nouveau thread depuis mon application est très rapide. Je pense que cela provoque une erreur indexoutobounds. J'ai été capable de deviner cela avec: http://www.jfree.org/phpBB2/viewtopic.php?p=68111 Erreur similaire. La solution semble être: Swing Thread Safe ProgrammingJfreechart indexoutofbounds exception
Ici, la solution consiste à utiliser SwingUtilities.invokeLater. Mais je n'arrive pas à comprendre comment l'utiliser dans mon application. Mon code est:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import static java.lang.Thread.sleep;
import org.jfree.chart.axis.ValueAxis;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
public class dataPlotter {
private static int x = 0;
private static boolean thread_start = false;
private static final double PI = 3.1428571;
private static boolean thread_run = true;
private static double voltage = 0;
private static boolean useSeries1 = true;
public static void main(String[] args) {
//create and configure window
JFrame window = new JFrame();
window.setTitle("Data Plotter GUI");
window.setSize(600, 400);
window.setLayout(new BorderLayout());
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//create a drop down box and connect button, then place that at the top of the window
JButton connectButton = new JButton("Start");
JPanel topPanel = new JPanel();
topPanel.add(connectButton);
window.add(topPanel, BorderLayout.NORTH);
//create the line graph
XYSeries series1 = new XYSeries("Voltage Characteristics");
XYSeries series2 = new XYSeries("Voltage Characteristics");
XYSeriesCollection dataset = new XYSeriesCollection(series1);
JFreeChart chart = ChartFactory.createXYLineChart("Sine Wave", "Time", "Voltage", dataset);
window.add(new ChartPanel(chart), BorderLayout.CENTER);
//set range of x axis and range of series
XYPlot xyPlot = chart.getXYPlot();
ValueAxis domainAxis = xyPlot.getDomainAxis();
ValueAxis rangeAxis = xyPlot.getRangeAxis();
rangeAxis.setRange(-1.5, 1.5);
domainAxis.setRange(0, 1000);
//Declaring thread
Thread thread;
thread = new Thread() {
@Override
public void run() {
thread_start = true;
int count_y = 0;
thread_run = true;
int count = 0;
while (thread_run) {
//create "Y" datapoint i.e. voltage
if (count_y < 800) {
count_y++;
} else {
count_y = 0;
}
voltage = Math.sin(2 * PI * count_y/800);
//add datapoint to CHART
try {
//use series 1 to accumulate 1000 datapoints
if(useSeries1){
synchronized (series1) {
if (series1.getItemCount() > 1000) {
domainAxis.setRange(x - 1001, x);
}
series1.add(x++, voltage);
sleep(1);
}
synchronized (series1) {
window.repaint();
}
synchronized (series1) {
if (series1.getItemCount() ==1001) {
dataset.removeAllSeries();
series2.clear();
domainAxis.setRange(0, 1000);
dataset.addSeries(series1);
useSeries1 = false;
sleep(5);
x = 0;
window.repaint();
}
}
} else{
synchronized (series2) {
if (series2.getItemCount() > 1000) {
domainAxis.setRange(x - 1001, x);
}
series2.add(x++, voltage);
sleep(1);
}
synchronized (series2) {
window.repaint();
}
synchronized (series2) {
if (series2.getItemCount() == 1001) {
dataset.removeAllSeries();
series1.clear();
domainAxis.setRange(0, 1000);
dataset.addSeries(series2);
useSeries1 = true;
sleep(5);
x = 0;
window.repaint();
}
}
}
} catch (Exception er) { }
}
thread_start = false;
}
};
//configure the connect button and use another thread to listen for data
connectButton.addActionListener(new ActionListener() {
@Override
@SuppressWarnings("empty-statement")
public void actionPerformed(ActionEvent e) {
if (connectButton.getText().equals("Start")) {
connectButton.setText("Stop");
thread.start();
} else {
//disconnect from the serial port
thread_run = false;
//while (thread_start);
connectButton.setText("Start");
//synchronized (series) {
//series.clear();
//}
//x = 0;
}
}
});
//Display winow
window.setVisible(true);
}
}
Vous semblez avoir le chariot avant le cheval car il est généralement préférable d'apprendre les concepts orientés objet et de threading avant d'essayer de faire des graphes GUI en temps réel. Vous voudrez peut-être envisager de reculer un peu et d'étudier intensivement ces bases avant de continuer, sinon je crains que vous soyez dans une situation de frustration grave. –
Même avec une seule série où j'ajoute des éléments et supprime des éléments, cela donne une erreur d'indexoutofbound. L'erreur n'apparaît pas avec de grands intervalles de sommeil. Je pense à créer 2 threads 1 pour l'accumulation de données et 1 pour la mise à jour de l'interface graphique, mais avoir et appelant une méthode ADD et une méthode REMOVE l'une après l'autre crée le problème principal. – EgLeO
Après avoir lu un petit sous-ensemble de JFreeChart, il n'utilise pas du tout synchronisé, donc le vôtre est inutile ... – Aubin