JavaFX自定义LineChartWithMarkers适配Java10:解决LineChartBuilder移除问题
我完全懂你时隔两年回归JavaFX开发遇到的懵圈感——Java 10里LineChartBuilder直接蒸发了!之前只知道它在Java 8被废弃,真到升级时才发现连替代方案都没头绪对吧?别慌,咱们一步步把代码改成Java 10兼容的版本。
先回顾下你之前的代码:
原有LineChartWithMarkersBuilder类
public class LineChartWithMarkersBuilder extends LineChartBuilder { private Axis<Number> xAxis ; private Axis<Number> yAxis ; private ObservableList<Series<Number,Number>> data ; public static LineChartWithMarkersBuilder create() { return new LineChartWithMarkersBuilder(); } public LineChartWithMarkersBuilder xAxis(Axis<Number> xAxis) { this.xAxis = xAxis ; return this ; } public LineChartWithMarkersBuilder yAxis(Axis<Number> yAxis) { this.yAxis = yAxis ; return this ; } public LineChartWithMarkers<Number, Number> build() { xAxis = new NumberAxis(); yAxis = new NumberAxis(); return new LineChartWithMarkers<Number, Number>( xAxis, yAxis); } }
自定义LineChartWithMarkers类
public class LineChartWithMarkers<X extends Number, Y extends Number> extends LineChart<X, Y> { private ObservableList<Data<Number, Number>> verticalMarkers; public LineChartWithMarkers(Axis<X> xAxis, Axis<Y> yAxis) { super(xAxis, yAxis); this.setCreateSymbols(false); verticalMarkers = FXCollections.observableArrayList(data -> new Observable[] {data.XValueProperty()}); verticalMarkers.addListener((InvalidationListener)observable -> layoutPlotChildren()); } (...) }
FXML中的使用方式
... <LineChartWithMarkers fx:id="chartFit" createSymbols="false" layoutX="14.0" layoutY="54.0" prefHeight="499.0" prefWidth="987.0" AnchorPane.bottomAnchor="162.0" AnchorPane.leftAnchor="14.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="54.0"> <xAxis> <NumberAxis side="BOTTOM" /> </xAxis> <yAxis> <NumberAxis side="LEFT" /> </yAxis> </LineChartWithMarkers> ...
解决方案:彻底抛弃Builder模式,用构造器+FXML原生支持
JavaFX从Java 9开始彻底移除了所有Builder类,官方推荐的替代方案就是直接用构造器,或者让自定义控件适配FXML的原生加载逻辑。
步骤1:删掉LineChartWithMarkersBuilder类
这个类完全不需要了,直接扔进回收站就行——Builder模式的功能咱们用其他方式替代。
步骤2:FXML代码完全不用改!
你现有的FXML写法已经完美适配Java 10了!因为<LineChartWithMarkers>标签嵌套<xAxis>和<yAxis>的方式,是FXML加载自定义控件的原生逻辑,只要你的自定义类有接收xAxis和yAxis的构造器,FXML就能自动识别并注入参数。
另外你用到的createSymbols="false"也能正常生效,因为父类LineChart已经提供了setCreateSymbols方法,FXML会自动调用对应的setter来绑定属性。
步骤3:Java代码中直接用构造器实例化
如果之前是用Builder创建控件实例,现在直接换成构造器调用就行:
// 替代原来的Builder链式调用 Axis<Number> xAxis = new NumberAxis(); Axis<Number> yAxis = new NumberAxis(); LineChartWithMarkers<Number, Number> chart = new LineChartWithMarkers<>(xAxis, yAxis); // 直接设置属性,和原来的Builder效果一致 chart.setCreateSymbols(false); chart.setPrefWidth(987.0); chart.setPrefHeight(499.0); // ... 其他属性按需设置
可选:自己实现链式调用(保留Builder的手感)
如果你特别喜欢Builder的链式写法,可以给LineChartWithMarkers加几个自定义的链式setter:
public class LineChartWithMarkers<X extends Number, Y extends Number> extends LineChart<X, Y> { // 原有代码... // 添加链式setter方法 public LineChartWithMarkers<X, Y> setCreateSymbols(boolean createSymbols) { super.setCreateSymbols(createSymbols); return this; } public LineChartWithMarkers<X, Y> setPrefWidth(double width) { super.setPrefWidth(width); return this; } public LineChartWithMarkers<X, Y> setPrefHeight(double height) { super.setPrefHeight(height); return this; } // 其他需要的属性同理 }
这样就能继续用熟悉的链式写法:
LineChartWithMarkers<Number, Number> chart = new LineChartWithMarkers<>(new NumberAxis(), new NumberAxis()) .setCreateSymbols(false) .setPrefWidth(987.0) .setPrefHeight(499.0);
补充:为什么Builder被移除?
JavaFX的Builder类在Java 8就被标记为废弃,核心原因是它们的功能完全可以通过构造器、FXML原生加载或者第三方库(比如Lombok的@Builder注解)替代,而且官方维护这些Builder类的成本太高,所以在Java 9及以后版本直接彻底移除了。
内容的提问来源于stack exchange,提问作者igorludi

