(упрощенный) жизненный цикл приложения JavaFX выглядит следующим образом: вызывается
Application.launch
, и это запускает инструментарий ect. - Создается экземпляр используемого класса
Application
. - Повторная обработка события / рендеринг / макет и т. Д.
- Когда JavaFX определяетон должен выключиться, выполнить некоторую очистку и
Application.launch
возвращает.
По этой причине код в методе main после
launch(args);
выполняется после закрытия GUI.
Кроме того, поскольку Application.launch
создает свой собственный экземпляр класса приложения, обновления графического интерфейса не будет.(Вы добавляете другой экземпляр в качестве наблюдателя).
Также обратите внимание, что ваше приложение зависает, пока выполняется длинная операция в потоке приложения JavaFX.По этой причине вам необходимо убедиться, что обновления модели выполняются в отдельном потоке.Это также требует, чтобы вы гарантировали, что обновления GUI выполняются в потоке приложения JavaFX (из соображений производительности JavaFX предполагает, что доступ к GUI осуществляется только из этого потока.).
Некоторые части вашего ChartModel
класс кажется странным:
data
- это static
, но dataName
- это не - Вы, кажется, заново изобретаете колесо: вместо этого вы можете просто использовать
LinkedHashMap<String, Double>
использования 2 массивов для хранения данных - доступ к данным не синхронизирован, что приводит к потенциальным проблемам параллелизма
Observable
устарело в Java 9 - в
updateCharData
длина строкового параметра используется в условии цикла и условии if
Следующий код демонстрирует запуск обновлений из метода start
и выполнение обновлений из отдельного потока.Это также изменяет способ хранения данных на LinkedHashMap
, чтобы избежать реализации функциональности, подобной карте.
public class MyBarChart extends Application implements Observer {
BarChart<String, Number> bc;
public void start(Stage stage) {
stage.setTitle("Graphique");
final CategoryAxis xAxis = new CategoryAxis();
final NumberAxis yAxis = new NumberAxis();
bc = new BarChart<String, Number>(xAxis, yAxis);
bc.setTitle("Etudiants");
xAxis.setLabel("Sections");
//xAxis.setTickLabelRotation(90);
yAxis.setLabel("Nombre d'élèves");
Scene scene = new Scene(bc, 800, 600);
stage.setScene(scene);
stage.show();
initModel();
}
private void initModel() {
String[] dataName = new String[]{"Informatique", "Infirmier", "Kine", "Compta"};
double[] data = new double[]{10, 20, 30, 40};
ChartModel cm = new ChartModel();
cm.setChartData(dataName, data);
cm.addObserver(this);
new Thread(() -> {
cm.updateCharData("Informatique", 50);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {//trt
}
cm.updateCharData("Informatique", 10);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {//trt
}
}).start();
}
@Override
public void update(Observable o, Object arg) {
if (o instanceof ChartModel) {
ChartModel cm = (ChartModel) o;
Map<String, Double> data = cm.getData();
// make sure to read the data from the thread that does the updates
// or make sure the data is synchronized
final XYChart.Series<String, Number>[] series = new XYChart.Series[data.size()];
int index = 0;
for (Map.Entry<String, Double> entry : cm.getData().entrySet()) {
XYChart.Series<String, Number> series1 = new XYChart.Series<>();
series1.setName(entry.getKey());
series1.getData().add(new XYChart.Data<>(entry.getKey(), entry.getValue()));
series[index] = series1;
index++;
}
// updates to the gui on the javafx application thread
Platform.runLater(() -> bc.getData().setAll(series));
}
}
public static void main(String[] args) {
launch(args);
}
}
public class ChartModel extends Observable {
private final Map<String, Double> data = new LinkedHashMap<>();
public Map<String, Double> getData() {
return data;
}
public void setChartData(String[] d, double[] dd) {
if (d.length != dd.length) {
throw new IllegalArgumentException();
}
for (int i = 0; i < d.length; i++) {
data.put(d[i], dd[i]);
}
setChanged();
notifyObservers();
}
public void updateCharData(String dataName, double newData) {
data.put(dataName, newData);
setChanged();
notifyObservers();
}
}