java - 如何从其他两个系列中获得一个系列?
问题描述
我正在 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);
}
}
解决方案
您可以通过向另外两个添加侦听器来实现 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()
由侦听器调用。
更新 2series1.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);
}
}
推荐阅读
- c++ - 我正在尝试从 void 函数打印,但它不会编译,因为它说它没有定义
- css - 材质 UI 波普尔样式
- c# - 这两个功能是等价的吗?
- c# - 如何设置服务以接收 ASP.NET Core 中的某些选项?
- javascript - 更改 React Native Maps 多边形中填充颜色的不透明度?
- javascript - 节点 js 渲染发布数据和原始 html
- xcode - 原型单元格宽度超出表格视图中的页面
- postgresql - Postgresql 解释命令
- java - 如何使用 DatePicker 元素中的日期作为 MPAndroidChart 上的 x 轴值?
- iframe - 具有与父文档相同域和端口的 src 的 iframe 不可编辑/禁用