再一次,当我使用JavaFX-Charts ...时,我挠头了...:-(
我有一个用例,需要替换图表中的所有系列,我从头开始创建所有内容。在清除之前的数据后添加时,图表将 default-color 的错误样式类分配给添加的系列的 some 。 更确切地说,分配的类别编号发生了变化……为什么他们在地球上采用模运算来实现,默认情况下,该模数仅限制为8(!)个不同的颜色符号组合...?!
前8个(提示:mod 8 ...)默认颜色是正确的:
default-color0
...
default-color7
,并且在第一次运行时,它再次继续,也正确,再次为0:
default-color0
...
default-color6 (for 15 series in my example)
第二次运行,我得到:
default-color0
...
default-color7
default-color7 <-- shift from here
default-color0
...
default-color5
如您所见,它被移动了两次,为7,然后一直运行到5。 再进行一次换班,继续:
default-color0
...
default-color7
default-color6 <-- shift from here
default-color7
default-color0
...
default-color4
移位量取决于序列数-对于16,一切正常,对于14,它每次移位2,依此类推。
在图表中,如果您看到图例在变化,这很明显...
我尝试了不同的数据替换方法,但没有一个成功,请参见下面的代码中的注释。 实际的解决方案是手动覆盖样式类,但在我看来这不是一个很漂亮的解决方案,由于任务类的进取习惯... wtf ?! >
无论如何-如果有人对此有任何帮助的想法?也许我想念什么?
注意:要查看奇怪的结果,请删除标记为 DIRTY-WORKAROUND-SOLUTION 的行。否则它将起作用...;-)
奖金问题:也许我很傻,正在使用JavaFX图表...有些事情很酷,但是很多时候,我对此感到很奇怪...还有更好的替代方法,您会建议我抽出来吗?
谢谢!
import javafx.application.Application;
import javafx.beans.InvalidationListener;
import javafx.scene.Scene;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.ScatterChart;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.util.ArrayList;
import java.util.List;
public class ChartSeriesReplacing extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
VBox root = new VBox();
ScatterChart<Number, Number> chart = new ScatterChart<>(new NumberAxis(), new NumberAxis());
Button refresh = new Button("Refresh");
refresh.setOnAction(clicked -> {
List<XYChart.Series<Number, Number>> seriesList = new ArrayList<>();
for (int i = 0; i < 15; i++) {
XYChart.Series<Number, Number> series = new XYChart.Series<>();
series.setName(i + "");
XYChart.Data<Number, Number> data = new XYChart.Data<>(Math.random(), Math.random());
int finalI = i;
data.nodeProperty().addListener(__ -> {
if (data.getNode() != null) {
data.getNode().getStyleClass().addListener((InvalidationListener) ___ -> {
System.out.println("[pre] Data #" + finalI + ": Style = " + data.getNode().getStyleClass());
// DIRTY-WORKAROUND-SOLUTION:
// (has to live in listener, otherwise the chart erases any custom styling on adding... :-/ )
String colorString = "default-color" + finalI % 8;
data.getNode().getStyleClass().removeIf(s -> s.startsWith("default-color") && !s.equals(colorString));
if (!data.getNode().getStyleClass().contains(colorString)) {
data.getNode().getStyleClass().add(colorString);
}
// --------------------------
System.out.println("[post] Data #" + finalI + ": Style = " + data.getNode().getStyleClass());
});
}
});
series.getData().add(data);
seriesList.add(series);
}
System.out.println("-----------------");
// What I tried:
// 1)
chart.getData().setAll(seriesList);
// 2)
// chart.dataProperty().setValue(FXCollections.observableArrayList(seriesList));
// 3)
// chart.getData().clear();
// 3a)
// chart.getData().addAll(seriesList);
// 3b)
// seriesList.forEach(series->chart.getData().add(series));
});
root.getChildren().add(chart);
root.getChildren().add(refresh);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
}
Java版本jdk1.8.0_171(x64)