[英]JavaFX Bind Label textProperty to multiple Properties changes
[英]JavaFX: Bind the textProperty from a Label to the size of an ObservableList
我是FX的新手,而不是Java的新手,所以请多多包涵! 我所拥有的是一个使用由ObservableList支持的JavaFX TableView的简单应用程序。
当我第一次启动应用程序时,我产生了另一个线程(来自Application的start方法)来侦听对日志文件的更改,并将另一个元素添加到ObservableList中,以便可以在TableView中立即看到该行。 我认为在包含ObservableList当前大小的窗口中放置一个Label将是有益的。 我试图将Label的textProperty绑定到ObservableList的大小。 我的第一次尝试产生了:
tableSizeLabel.textProperty().bind(Bindings.size((tableView.getItems())).asString());
但是我相信我对Bindings API有误解。 我意识到ObservableList.size()返回一个常规的int而不是它正常工作所必需的ObservableValue,但是我认为Bindings类有一个静态方法为我创建一个。
后端模型将列表包含为静态变量(我省略了“侦听变更”部分):
public class LogFileListener implements Runnable {
private static final ObservableList<SNMPTrap> model = FXCollections.observableArrayList();
@Override
public void run() {
String line = null;
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(fileLocation)))) {
while ((line = br.readLine()) != null) {
model.add(parseTrap(line));
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static ObservableList<SNMPTrap> getModel() {
return model;
}
}
应用类别:
public class TableDisplay extends Application {
@Override
public void start(Stage stage) throws Exception {
new Thread(new LogFileListener()).start();
Parent root = FXMLLoader.load(getClass().getResource("path/to/FXML"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
控制器类:
public class TableDisplayController implements Initializable {
@FXML
private TableView<SNMPTrap> tableView;
@FXML
private Label tableSizeLabel;
@Override
public void initialize(URL url, ResourceBundle rb) {
tableView.setItems(LogFileListener.getModel());
tableSizeLabel.textProperty().bind(Bindings.size((tableView.getItems())).asString());
}
在FX中甚至可能吗? 我是否需要向整个ObservableList添加更改侦听器,然后才使用getSize()更新Label?
提前致谢!
您的绑定语句对于您要实现的目标是正确的(将Label的text属性绑定到ObservableList的大小)。
您的代码存在并发问题。 将会发生的是LogFileListener在其自己的线程中运行,更新了项目列表,并且这些项目在LogFileListener线程中进行了更新,从而触发了JavaFX应用程序线程对场景图的更新。 这是一件“坏事”,因为JavaFX使用单个GUI线程。
您需要做的是确保绑定触发器和表项更新仅在JavaFX应用程序线程上发生(并且您可能需要以一种有效的方式进行更新,以免JavaFX事件处理器不会因太多更新而过载)电话)。
当前解决方案的一个简单解决方案是使用以下代码。
final SNMPTrap trap = parseTrap(line);
Platfrom.runLater(new Runnable() {
@Override public void run() {
model.add(trap);
}
});
您的应用程序可能会受益于更复杂的方法。 您可以在StackOverflow上搜索有关Platform.runLater,Task,Service和JavaFX并发性主题的相关问题,还可以查看有关JavaFX和Task javadoc并发性的Oracle文档,以更好地理解所有这些工作原理以及您的选择是什么。 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.