java - Javafx:如何将 ComboBox 项动态绑定到从数据库更新自身的 observablelist
问题描述
我正在尝试将我的 javafx 组合框项目绑定到可观察列表;当列表更新时,组合框项目也会更新(添加、删除或修改)。我尝试将侦听器添加到组合框项目,但仍然得到“不在 FX 应用程序线程上”异常。这是我的代码:
模型
{
…
private ObservableList<String> programList = FXCollections.observableArrayList();
…
some code initialize programList from database
…
private ListProperty<String> programListProperty = new SimpleListProperty<>(programList);
…
some code update programList periodically
…
}
和控制器
{
@FXML ComboBox programComboBox;
model.programListProperty().addListener((v, oldValue, newValue) ->
Platform.runLater(() -> {
programComboBox.getItems().clear();
programComboBo.getItems().add(every item in model.programList);
}));
}
我也试过这种方式,但都行不通
{
@FXML ComboBox programComboBox;
programComboBox.itemsproperty().bind(model.programListProperty());
}
解决方案
注意:此解决方案对您的实现做了一些假设,因为您没有提供代码的最小、完整和可验证的示例。
您不需要为此使用绑定。使用ComboBox
anObservableList
来填充其项目。这里的关键字是observable。这意味着当底层List
更改时,ComboBox
将“看到”更改并自动更新其显示的项目。
ComboBox
您使用该方法初始化setItems()
,并将其ObservableList
作为参数传递:
comboBox.setItems(programList);
从那里,无论何时programList
更新(添加、删除项目等),ComboBox
都将反映更改,而无需您提供任何进一步的代码。
查看以下完整示例:
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
public class ComboBoxListenerExample extends Application {
// This is our ObservableList that will hold our ComboBox items
private ObservableList<String> items = FXCollections.observableArrayList();
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
// Simple interface
VBox root = new VBox(5);
root.setPadding(new Insets(10));
root.setAlignment(Pos.CENTER);
// Simple ComboBox
ComboBox<String> comboBox = new ComboBox<>();
// Let's "permanently" set our ComboBox items to the "items" ObservableList. This causes the
// ComboBox to "observe" the list for changes
comboBox.setItems(items);
// Create a button that will reload data from our "database"
Button button = new Button("Refresh Data");
// The items.setAll()` method replaces all items in the list with our new list of items
button.setOnAction(event -> items.setAll(reloadDatabase()));
root.getChildren().addAll(comboBox, button);
// Show the Stage
primaryStage.setWidth(300);
primaryStage.setHeight(300);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
// Sample method to simulate reloading the database information
private List<String> reloadDatabase() {
List<String> items = new ArrayList<>();
for (int i = 0; i < 5; i++) {
items.add(getRandomWord());
}
return items;
}
// Just a helper method specific for this example; it simply returns a random word.
// This is used to simulate loading new data from the database
private String getRandomWord() {
List<String> words = Arrays.asList("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Red", "Blue", "Green", "Yellow", "Left", "Right", "Top", "Bottom");
Random random = new Random();
return words.get(random.nextInt(words.size()));
}
}
运行示例后,ComboBox
为空。每次您点击“刷新数据”按钮时,底层证券ObservableList
, items
, 都会更新一个新的随机项目列表;ComboBox
更改以立即反映这些更改。
不在 JavaFX 应用程序线程上:
现在,那个错误信息呢?StackOverflow 上有很多问题和答案已经解决了这个问题,但这里有一个简短的解释:
我假设您正在后台线程上从数据库加载数据,这很好! 但是,您不能从该线程对 UI 进行任何更改或更新。所有 UI 更新都需要在 JavaFX 应用程序线程上完成。
这很容易实现。当您更新List
调用数据库方法时,将该更新包装在Platform.runLater()
调用中:
Platform.runLater(() -> programList.setAll(yourNewList));
这会将列表的更新安排在 JFX 应用程序线程上。问题解决了!
推荐阅读
- sql-server - 使用表达式将日期格式 M/d/yyy hh:mm:ss 更改为 yyyy-MM-dd
- javascript - PWA:如何访问客户端本地存储的 manifest.json 版本
- c++ - 如何在模板中编写朋友(操作员)方法?
- html - 如何更改 Chrome 的 HTML5 进度条控件的颜色
- xcode - Xcode 无效的 zip 文件
- reactjs - React:尝试使用 react hook useEffect 重写 ComponentDidUpdate(prevProps),但它在应用程序启动时触发
- node.js - AWS Elasticsearch:putSettings“不允许”的关闭索引?
- sql - 选择记录,直到值重复
- java - 我的 jpaRepository.findAll() 中的可分页参数返回 SqlSyntaxErrorException
- c# - 在 blazor 项目中使用 npm install