我正在JavaFX中构建XYChart。它包含两个系列(系列1&2)和第三个系列(系列3),其值应为系列1和2的总和。
现在,如果对系列1或2的值进行了更改(添加,删除,更改等),则系列3应该自动更新。
实现此目标的最佳方法是什么?
谢谢。
package lineChart;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.stage.Stage;
public class LineChartSample extends Application {
@Override
public void start(Stage stage) {
final NumberAxis xAxis = new NumberAxis();
final NumberAxis yAxis = new NumberAxis();
final LineChart<Number, Number> lineChart = new LineChart<Number, Number>(xAxis, yAxis);
XYChart.Series series1 = new XYChart.Series();
series1.getData().add(new XYChart.Data(1, 10));
series1.getData().add(new XYChart.Data(10, 20));
series1.getData().add(new XYChart.Data(20, 30));
lineChart.getData().add(series1);
XYChart.Series series2 = new XYChart.Series();
series2.getData().add(new XYChart.Data(1, 20));
series2.getData().add(new XYChart.Data(10, 30));
series2.getData().add(new XYChart.Data(20, 40));
lineChart.getData().add(series2);
XYChart.Series series3 = new XYChart.Series();
// series3 = series1 + series2
series3.getData().add(new XYChart.Data(1, 10 + 20));
series3.getData().add(new XYChart.Data(10, 20 + 30));
series3.getData().add(new XYChart.Data(20, 30 + 40));
lineChart.getData().add(series3);
Scene scene = new Scene(lineChart, 800, 600);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
更新1 我已经更新了示例代码。如果我运行此代码,则第3序列会对从第1序列或第2序列中添加或删除数据对象作出反应。但是不幸的是,它对更改数据对象的值没有反应。
import javafx.application.Application;
import javafx.collections.ListChangeListener;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Data;
import javafx.stage.Stage;
public class LineChartSample extends Application {
private static int updateCounter = 1;
private XYChart.Series<Integer, Integer> series1, series2, series3;
@Override
public void start(Stage stage) {
final NumberAxis xAxis = new NumberAxis();
final NumberAxis yAxis = new NumberAxis();
final LineChart<Integer, Integer> lineChart = new LineChart(xAxis, yAxis);
series1 = new XYChart.Series<>();
series1.getData().add(new XYChart.Data(1, 10));
series1.getData().add(new XYChart.Data(10, 20));
series1.getData().add(new XYChart.Data(20, 30));
lineChart.getData().add(series1);
series2 = new XYChart.Series<>();
series2.getData().add(new XYChart.Data(1, 20));
series2.getData().add(new XYChart.Data(10, 30));
series2.getData().add(new XYChart.Data(20, 40));
lineChart.getData().add(series2);
series3 = new XYChart.Series<>();
lineChart.getData().add(series3);
bindDataSeieses();
Scene scene = new Scene(lineChart, 800, 600);
stage.setScene(scene);
stage.show();
// update 1
updateSumSeries();
// update 2
series1.getData().remove(0);
// update 3
series1.getData().add(new XYChart.Data(1, 50));
// No update :-(
series1.getData().get(0).setYValue(200);
}
private void bindDataSeieses() {
series1.getData().addListener((ListChangeListener<Data<Integer, Integer>>) c -> updateSumSeries());
series2.getData().addListener((ListChangeListener<Data<Integer, Integer>>) c -> updateSumSeries());
}
private void updateSumSeries() {
System.out.println("Update " + updateCounter++);
// todo enhance to support series of different length
if (series1.getData().size() != series2.getData().size())
return;
series3.getData().clear();
for (int index = 0; index < series1.getData().size(); index++) {
int xValue = series1.getData().get(index).getXValue();
int yValue = series1.getData().get(index).getYValue() + series2.getData().get(index).getYValue();
series3.getData().add(new Data<>(xValue, yValue));
}
}
public static void main(String[] args) {
launch(args);
}
}
答案 0 :(得分:0)
您可以通过向其他两个添加侦听器来实现3ed系列的动态更新:
import javafx.application.Application;
import javafx.collections.ListChangeListener;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Data;
import javafx.stage.Stage;
public class LineChartSample extends Application {
private XYChart.Series<Integer, Integer> series1, series2, series3;
@Override
public void start(Stage stage) {
final NumberAxis xAxis = new NumberAxis();
final NumberAxis yAxis = new NumberAxis();
final LineChart<Integer, Integer> lineChart = new LineChart(xAxis, yAxis);
series1 = new XYChart.Series<>();
series1.getData().add(new XYChart.Data(1, 10));
series1.getData().add(new XYChart.Data(10, 20));
series1.getData().add(new XYChart.Data(20, 30));
lineChart.getData().add(series1);
series2 = new XYChart.Series<>();
series2.getData().add(new XYChart.Data(1, 20));
series2.getData().add(new XYChart.Data(10, 30));
series2.getData().add(new XYChart.Data(20, 40));
lineChart.getData().add(series2);
series3 = new XYChart.Series<>();
lineChart.getData().add(series3);
bindDataSeieses();
Scene scene = new Scene(lineChart, 800, 600);
stage.setScene(scene);
stage.show();
}
private void bindDataSeieses() {
series1.getData().addListener((ListChangeListener<Data<Integer, Integer>>) c -> updateSumSeries());
series2.getData().addListener((ListChangeListener<Data<Integer, Integer>>) c -> updateSumSeries());
updateSumSeries();
}
private void updateSumSeries() {
//todo enhance to support series of different length
if(series1.getData().size() != series2.getData().size())
throw new IllegalArgumentException("series1 and series2 must be of same length");
series3.getData().clear();
for (int index = 0; index < series1.getData().size(); index++){
int xValue = series1.getData().get(index).getXValue();
//todo verify series1.getData().get(index).getXValue() == series2.getData().get(index).getXValue()
int yValue = series1.getData().get(index).getYValue() + series2.getData().get(index).getYValue();
series3.getData().add(new Data<>(xValue, yValue));
}
}
public static void main(String[] args) {
launch(args);
}
}
编辑:对更新后的代码的响应:
不需要更新1。 updateSumSeries()
由侦听器调用。
更新2使series1.getData().size() != series2.getData().size()
为真,因此引发了IllegalArgumentException
。注意您的例外情况。
以下代码通过单击按钮进行演示和编辑:
public class LineChartSample extends Application {
private XYChart.Series<Integer, Integer> series1, series2, series3;
@Override
public void start(Stage stage) {
final NumberAxis xAxis = new NumberAxis();
final NumberAxis yAxis = new NumberAxis();
final LineChart<Integer, Integer> lineChart = new LineChart(xAxis, yAxis);
series1 = new XYChart.Series<>();
series1.getData().add(new XYChart.Data(1, 10));
series1.getData().add(new XYChart.Data(10, 20));
series1.getData().add(new XYChart.Data(20, 30));
lineChart.getData().add(series1);
series2 = new XYChart.Series<>();
series2.getData().add(new XYChart.Data(1, 20));
series2.getData().add(new XYChart.Data(10, 30));
series2.getData().add(new XYChart.Data(20, 40));
lineChart.getData().add(series2);
series3 = new XYChart.Series<>();
lineChart.getData().add(series3);
bindDataSeieses();
BorderPane root = new BorderPane(lineChart);
Button btn = new Button("Add");
btn.setOnAction(e->series1.getData().set(0, new Data<>(1, 200)));
root.setBottom(btn);
Scene scene = new Scene(root, 800, 600);
stage.setScene(scene);
stage.show();
}
private void bindDataSeieses() {
series1.getData().addListener((ListChangeListener<Data<Integer, Integer>>) c -> updateSumSeries());
series2.getData().addListener((ListChangeListener<Data<Integer, Integer>>) c -> updateSumSeries());
updateSumSeries();
}
private void updateSumSeries() {
//todo enhance to support series of different length
if(series1.getData().size() != series2.getData().size())
throw new IllegalArgumentException("series1 and series2 must be of same length");
series3.getData().clear();
for (int index = 0; index < series1.getData().size(); index++){
int xValue = series1.getData().get(index).getXValue();
//todo verify series1.getData().get(index).getXValue() == series2.getData().get(index).getXValue()
int yValue = series1.getData().get(index).getYValue() + series2.getData().get(index).getYValue();
series3.getData().add(new Data<>(xValue, yValue));
}
}
public static void main(String[] args) {
launch(args);
}
}