如何在JavaFX中广播事件

时间:2015-07-29 10:26:14

标签: java javafx javafx-8

给定JavaFX应用程序,其中多个演示者和视图以层次结构组织。如何将父级演示者的事件广播到子演示者/视图?

我的架构如下所示:我有一个位于层次结构顶部的MainPresenter

public class MainPresenter {

    @FXML private TreeView<String> navigation;
    @FXML private AnchorPane       contentView;
    @Autowired private MainView    mainView;
    @Autowired private DetailView  detailView;

    @FXML
    public void initialize() {

        // register a handler for selection of treeview items
        navigation.getSelectionModel().selectedItemProperty().addListener(
            new ChangeListener<TreeItem<String>>() {
                // ...          
                contentView.getChildren().clear();
                contentView.getChildren().add(detailView);
                contentView.fireEvent(new ResourceEvent(ResourceEvent.SELECTED, model));
                // ...
            }
        );
    }
}

还有一个演示者用于所选项目的详细视图:

public class DetailPresenter {

    @Autowired private DetailView       view;

    @PostConstruct
    public void postInit() {
        // is being executed
        view.getView().addEventHandler(ResourceEvent.SELECTED, (event) -> {
            // not being invoked
        });
    }
}

我想要实现的是,无论何时在TreeView中选择项目,都应将此项目的DetailView添加到场景图(工作)中,并应通知DetailPresenter从后端服务加载资源。 对此的一个解决方案是简单地在DetailPresenter中自动装配MainPresenter,这不是我想要的。我想松耦合。正如我从文档on Event Handling中假设的那样,事件被分派到场景图中的所有节点,然后冒泡回到场景的根部。由于我的EventHandler中的DetailPresenter未被调用,因此我认为该事件未被传递下来。

我的问题是,如何实现这一目标?

1 个答案:

答案 0 :(得分:0)

MyModel.java

public class MyModel {
  private StringProperty myString = new SimpleStringProperty();
  public void setMyString(String myString) { this.myString.set(myString); }
  public String getMyString() { return myString.get(); }
  public StringProperty getMyStringProperty() { return myString; }
}

然后创建MyModel的实例作为单例bean(看起来你正在使用Spring)。并将模型注入需要的地方:

@Bean
public MyModel myModel() {
  return new MyModel();
}

然后将其注入并绑定到属性:

public class MyPresenter {
  @FXML TextField myTextField;
  @Autowired MyModel myModel;

  public void initialize() {
    myTextField.textProperty().bind(myModel.getMyStringProperty());
  }
}

如果现在有人更新了myString属性,则用户界面myTextField也会更新。

您也可以在这些属性上注册一些自定义处理程序或使用twoWayBinding。

因此您不必将其用作UI元素,但也可以将其用作某种数据管道。