如何向子控制器发出变化信号/通知超级控制器?

时间:2015-09-08 17:54:13

标签: scala javafx architecture signals-slots scalafx

在JavaFX中,您如何建模以下内容:

我在场景中显示客户列表。在左侧有一个右侧的表格( contentPane ),显示当前所选客户的详细信息。

(相关部分)主要管制员:

@jfxf.FXML
protected def newButtonPressed(): Unit =
{
    contentPane.getChildren.clear
    contentPane.getChildren.add(FXMLLoader.load(GUILoader.load("customers/form.fxml")))
}

有一个按钮可添加新客户。单击此按钮而不是打开弹出窗口,我替换场景的"详细信息" -part并在那里添加表单。

现在对于这个表单(设计 - 就像其余的GUI - 在SceneBuilder中并保存为.fxml)我使用另一个控制器。

class Form extends Main with jfxf.Initializable
{
    @jfxf.FXML
    private var foreNameTextField: jfxsc.TextField = _
    @jfxf.FXML
    private var lastNameTextField: jfxsc.TextField = _
    @jfxf.FXML
    private var ageTextField: jfxsc.TextField = _

    override def initialize(url: URL, resourceBundle: ResourceBundle): Unit =
    {

    }

    @jfxf.FXML
    protected def ok(): Unit =
    {
        // TODO validation
        val newPerson = new Person(-1, foreNameTextField.getText, lastNameTextField.getText, ageTextField.getText.toInt)
       // Save to DB
       // Close whole form
    }
} 

当我填写新客户的详细信息时,我点击另一个按钮(调用ok())并将其保存到数据库。

我现在要做的是关闭表单并将其替换为详细信息表单。

像在主控制器中调用受保护的方法一样:

protected def clearDetails(): Unit =
{
   contentPane.getChildren.clear
   contentPane.getChildren.add(savedOldDetails)
}

当然不会工作。 (将抛出运行时异常,因为sub / form-controller中没有contentpane(即使我保护它)

在Qt(C ++)中,我使用信号/插槽并相应地连接它们。

似乎在JavaFX中没有类似的东西。我该如何分享这些信息?

我是否需要创建一个"超级控制器"对于contentPane?

1 个答案:

答案 0 :(得分:1)

(我不知道Scala,所以我会用Java写这个,希望没问题。)

您可以在Form控制器中定义一个可观察属性,并在从主控制器加载表单时观察它:

public class Form implements Initializable {

    private final ObjectProperty<Person> person = new SimpleObjectProperty<>(null);

    public ObjectProperty<Person> personProperty() {
        return person ;
    }

    public final Person getPerson() {
        return personProperty().get();
    }

    public final void setPerson(Person person) {
        personProperty().set(person);
    }

    // ... code you had before...

    @FXML
    protected void ok() {
        Person person = new Person(-1, foreNameTextField.getText(), lastNameTextField.getText(), ageTextField.getText());
        // save to DB...
        personProperty().set(person);
    }
}

现在在主控制器中,按如下方式加载表单:

@FXML
protected void newButtonPressed() {
    contentPane.getChildren().clear();
    FXMLLoader loader = new FXMLLoader(getClass().getResource("customers/form.fxml"));
    Parent form = loader.load();
    Form formController = loader.getController();
    formController.personProperty().addListener((obs, oldPerson, newPerson) {
        if (newPerson != null) {
            // clear form, etc, e.g.
            clearDetails();
        }
    });
    contentPane.getChildren().add(form);
}