[英]JavaFx and binding XYChart.Series
我在更新圖表時遇到了一些問題
我有 class 圖表
public class Chart {
public LineChart<String, Number> createChart() {
// defining the axes
final CategoryAxis xAxis = new CategoryAxis(); // we are gonna plot against time
final NumberAxis yAxis = new NumberAxis();
xAxis.setLabel("Time/s");
xAxis.setAnimated(false); // axis animations are removed
yAxis.setLabel("Value");
yAxis.setAnimated(false); // axis animations are removed
// creating the line chart with two axis created above
final LineChart<String, Number> lineChart = new LineChart<>(xAxis, yAxis);
lineChart.setAnimated(false); // disable animations
// defining a series to display data
XYChart.Series<String, Number> series = new XYChart.Series<>();
series.setName("Data Series");
// add series to chart
lineChart.getData().add(series);
return lineChart;
}
}
和主class
public class Main extends Application {
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
private Service service;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Hello World");
primaryStage.setWidth(500);
primaryStage.setHeight(500);
Chart chart = new Chart();
LineChart<String, Number> lineChart = chart.createChart();
// setup scene
Scene scene = new Scene(lineChart, 800, 600);
primaryStage.setScene(scene);
createService();
primaryStage.show();
startService();
// First variant
Platform.runLater(() -> lineChart.getData().get(0).getData().add((XYChart.Data<String, Number>) service.valueProperty().getValue()));
//Second variant
lineChart.getData().get(0).getData().add((XYChart.Data<String, Number>) service.valueProperty().getValue());
//Third variant
lineChart.getData().get(0).dataProperty().bind(service.valueProperty());
}
private void createService() {
service = new Service<ObservableList<XYChart.Data<String, Number>>>() {
@Override
protected Task<ObservableList<XYChart.Data<String, Number>>> createTask() {
return new Task<ObservableList<XYChart.Data<String, Number>>>() {
Date now;
Integer random;
@Override
protected ObservableList<XYChart.Data<String, Number>> call() throws InterruptedException {
for (int i = 0; i < 10; i++) {
now = new Date();
random = ThreadLocalRandom.current().nextInt(10);
System.out.println(simpleDateFormat.format(now) + " " + random);
updateValue(FXCollections.observableArrayList(new XYChart.Data(simpleDateFormat.format(now), random)));
Thread.sleep(500);
}
return FXCollections.observableArrayList(new XYChart.Data(simpleDateFormat.format(now), random));
}
};
}
};
}
private void startService() {
if (!service.isRunning()) {
service.reset();
service.start();
}
}
}
Main class 的第一個和第二個變體在線程“JavaFX 應用程序線程”java.lang.NullPointerException 中拋出異常異常並且不更新我的圖表,但第三個更新它但它更新了,但我需要為我的圖表添加新值形象的
如何更新我的代碼以將所有 10 個值添加到圖中,而不是僅添加 1 個或僅最后一個?
我不得不將我的主要 class 更改為
public class Main extends Application {
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
private LineChart<String, Number> lineChart;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Hello World");
primaryStage.setWidth(500);
primaryStage.setHeight(500);
Chart chart = new Chart();
lineChart = chart.createChart();
// setup scene
Scene scene = new Scene(lineChart, 800, 600);
primaryStage.setScene(scene);
createService();
primaryStage.show();
}
private void createService() {
Task<Void> task = new Task<Void>() {
Date now;
Integer random;
@Override
protected Void call() throws InterruptedException {
for (int i = 0; i < 10; i++) {
now = new Date();
random = ThreadLocalRandom.current().nextInt(10);
System.out.println(simpleDateFormat.format(now) + " " + random);
Platform.runLater(() -> updateChart(now, random));
Thread.sleep(500);
}
return null;
}
};
Thread thread = new Thread(task);
thread.setDaemon(true);
thread.start();
}
private void updateChart(Date now, Integer random) {
lineChart.getData().get(0).getData().add(new XYChart.Data(simpleDateFormat.format(now), random));
}
}
valueProperty.getValue()
可能是 null 因為服務任務執行可能還沒有達到setValue
調用。 但最重要的是這個演員陣容
Platform.runLater(() -> lineChart.getData().get(0).getData().add(/*here -->*/(XYChart.Data<String, Number>) service.valueProperty().getValue()));
沒有意義。 服務valueProperty
類型為ObservableList<XYChart.Data<String, Number>>
行中指定
service = new Service<ObservableList<XYChart.Data<String, Number>>>()
如果您想添加當前服務值,您寧願使用ObservableList::addAll
方法並將值轉換為列表類型:
Platform.runLater(() -> lineChart.getData().get(0).getData().addAll((ObservableList<XYChart.Data<String, Number>>)service.valueProperty().getValue()));
此外,由於您知道稍后將擁有什么類型的服務,您已經可以通過更改在聲明中指定其完整類型:
private Service service;
進入
private Service<ObservableList<XYChart.Data<String, Number>>> service;
結果只是:
Platform.runLater(() -> lineChart.getData().get(0).getData().addAll(service.getValue()));
與第一個變體的故事基本相同,但另外您不在 UI 線程上進行更改,因此這可能會在更新圖表時造成麻煩。
您使用僅包含一個元素的列表覆蓋服務value
:
// each time new list!
updateValue(FXCollections.observableArrayList(new XYChart.Data(simpleDateFormat.format(now), random)));
在服務定義中,您應該創建一個列表,並且 append 指向該列表
private void createService() {
service = new Service<ObservableList<XYChart.Data<String, Number>>>() {
@Override
protected Task<ObservableList<XYChart.Data<String, Number>>> createTask() {
return new Task<ObservableList<XYChart.Data<String, Number>>>() {
Date now;
Integer random;
// Specify ONE list
ObservableList<XYChart.Data<String, Number>> data = FXCollections.observableArrayList();
@Override
protected ObservableList<XYChart.Data<String, Number>> call() throws InterruptedException {
updateValue(data);
for (int i = 0; i < 10; i++) {
now = new Date();
random = ThreadLocalRandom.current().nextInt(10);
System.out.println(simpleDateFormat.format(now) + " " + random);
// Add points to the data (on UI thread to have chart updated properly!)
Platform.runLater(() -> data.add(new XYChart.Data(simpleDateFormat.format(now), random)));
Thread.sleep(500);
}
return data;
}
};
}
};
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.