# JavaFxDemo **Repository Path**: ShiGuang0829/java-fx-demo ## Basic Information - **Project Name**: JavaFxDemo - **Description**: 20250407 面试题 JavaFx的双向绑定和MVVM 例子 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-04-07 - **Last Updated**: 2025-04-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README JavaFx01模块不用看,只是为了验证原生启动方式。 ![image-20250407205412889](./assets/image-20250407205412889.png) ![image-20250407205421200](./assets/image-20250407205421200.png) ![image-20250407205430518](./assets/image-20250407205430518.png) ## JavaFx03模块 ![image-20250408193110182](./assets/image-20250408193110182.png) ![image-20250408193028113](./assets/image-20250408193028113.png) 以下是关于 JavaFX 双向绑定的深度解析和进阶用法示例,包含不同场景下的实现方案: --- ### 一、双向绑定的核心机制 JavaFX 通过 `Property` 体系和 `Bindings` 工具类实现绑定,双向绑定的核心方法是: ```java propertyA.bindBidirectional(propertyB); // 双向绑定 propertyA.unbindBidirectional(propertyB); // 解除绑定 ``` --- ### 二、基础到进阶的双向绑定用法 #### 1. 基础数据类型双向绑定 ```java // String 类型双向绑定 StringProperty textFieldContent = new SimpleStringProperty(); StringProperty viewModelValue = new SimpleStringProperty(); textField.textProperty().bindBidirectional(viewModelValue); // 数值类型转换绑定 IntegerProperty sliderValue = new SimpleIntegerProperty(); DoubleProperty progressValue = new SimpleDoubleProperty(); Bindings.bindBidirectional( sliderValue, progressValue, new NumberConverter() // 自定义数值转换器 ); ``` #### 2. 对象属性双向绑定 ```java // 自定义对象属性绑定 ObjectProperty selectedPerson = new SimpleObjectProperty<>(); ObjectProperty currentSelection = new SimpleObjectProperty<>(); selectedPerson.bindBidirectional(currentSelection); ``` #### 3. 容器控件双向绑定(高级示例) ```java // ListView 选择项双向绑定 ListView listView = new ListView<>(); ObjectProperty selectedItem = new SimpleObjectProperty<>(); // 双向绑定实现 listView.getSelectionModel().selectedItemProperty().bindBidirectional(selectedItem); // 集合数据双向绑定 ObservableList backendList = FXCollections.observableArrayList(); ObservableList uiList = listView.getItems(); Bindings.bindContentBidirectional(backendList, uiList); ``` --- ### 三、高级双向绑定场景 #### 1. 自定义双向绑定转换器(数据格式转换) ```java // 日期选择器与字符串的转换 DatePicker datePicker = new DatePicker(); StringProperty dateString = new SimpleStringProperty(); Bindings.bindBidirectional( datePicker.valueProperty(), dateString, new StringConverter<>() { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); @Override public String toString(LocalDate date) { return date != null ? date.format(formatter) : ""; } @Override public LocalDate fromString(String string) { return StringUtils.isEmpty(string) ? null : LocalDate.parse(string, formatter); } } ); ``` #### 2. 条件双向绑定(动态绑定控制) ```java BooleanBinding condition = checkbox.selectedProperty(); StringProperty source = textField.textProperty(); StringProperty target = label.textProperty(); // 条件成立时建立双向绑定 source.addListener((obs, old, newVal) -> { if (condition.get()) { target.bindBidirectional(source); } else { target.unbindBidirectional(source); } }); ``` #### 3. 表单与模型双向绑定(复杂对象) ```java // 使用 JavaFX Beans 特性 public class UserForm { private final StringProperty name = new SimpleStringProperty(); private final IntegerProperty age = new SimpleIntegerProperty(); public void bindBidirectional(User user) { name.bindBidirectional(user.nameProperty()); age.bindBidirectional(user.ageProperty()); } } // 在 ViewModel 中使用 UserForm form = new UserForm(); form.bindBidirectional(dataModel.getCurrentUser()); ``` --- ### 四、容器控件的深度绑定 #### 1. TableView 双向绑定 ```java // 表格列绑定 TableColumn nameColumn = new TableColumn<>("Name"); nameColumn.setCellValueFactory(cellData -> cellData.getValue().nameProperty()); // 整个表格数据绑定 ObservableList backendData = FXCollections.observableArrayList(); tableView.setItems(backendData); // 选择项绑定 ObjectProperty selectedUser = new SimpleObjectProperty<>(); tableView.getSelectionModel().selectedItemProperty().bindBidirectional(selectedUser); ``` #### 2. TreeView 结构绑定 ```java // 树形结构双向绑定 TreeItem root = new TreeItem<>("Root"); ObservableList> backendNodes = FXCollections.observableArrayList(); TreeView treeView = new TreeView<>(root); root.getChildren().bindContentBidirectional(backendNodes); ``` --- ### 五、页面级双向绑定架构 #### 1. 多视图协调绑定 ```java // 主从视图同步示例 public class MasterDetailViewModel { private final ObjectProperty selectedItem = new SimpleObjectProperty<>(); private final DetailViewModel detailVM = new DetailViewModel(); public MasterDetailViewModel() { // 主从视图双向绑定 selectedItem.bindBidirectional(detailVM.currentItemProperty()); } } ``` #### 2. 跨组件通信绑定 ```java // 使用 EventBus 实现松散耦合 public class EventBusBindingExample { private final EventBus eventBus = new EventBus(); // 组件A发布事件 textField.textProperty().addListener((obs, old, newVal) -> { eventBus.publish(new TextUpdateEvent(newVal)); }); // 组件B订阅事件 eventBus.subscribe(TextUpdateEvent.class, event -> { label.textProperty().set(event.getText()); }); } ``` --- ### 六、双向绑定的注意事项 1. **内存管理**:及时调用 `unbindBidirectional()` 防止内存泄漏 2. **循环更新**:在监听器中添加更新标记防止死循环 ```java boolean updating = false; propertyA.addListener((obs, old, newVal) -> { if (!updating) { updating = true; propertyB.set(newVal); updating = false; } }); ``` 3. **线程安全**:确保在 JavaFX 应用线程操作绑定 --- 以上示例展示了 JavaFX 双向绑定的不同层次用法,开发者可以根据实际需求组合使用这些模式,结合 JavaFX 的 `Observable*` 系列类和 `Bindings` 工具类,可以构建出高度响应式的复杂 UI 应用。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ###参考资料 双向绑定基础用法: https://blog.51cto.com/u_16213461/9192254 https://www.w3cschool.cn/java/codedemo-484049765.html https://www.w3cschool.cn/java/codedemo-484049763.html https://www.imooc.com/wenda/detail/677461 双向绑定进阶用法: https://blog.csdn.net/weixin_30299319/article/details/146926511 https://blog.csdn.net/qq_34912208/article/details/145712875 https://wenku.csdn.net/column/2p2jjsjek0 https://blog.csdn.net/2301_78772942/article/details/144796634 https://www.cnblogs.com/lcyxy/p/12675732.html https://blog.51cto.com/u_16213333/13526748