繁体   English   中英

JavaFX:将textProperty从Label绑定到ObservableList的大小

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM