JavaFX Dialogbox通信

时间:2014-03-25 20:02:38

标签: java dialog javafx fxml stage

我是JavaFX的新手,并尝试创建一个确认对话框。 我已经知道JavaFX中的对话框中没有真正的构建,所以我自己创建了一个这样的:

@FXML
public void delBox() {
     try {
        Stage dialogStage = new Stage();
        AnchorPane root = FXMLLoader.load(getClass().getResource("Dialog.fxml"));
        Scene scene = new Scene(root);
        dialogStage.setScene(scene);
        dialogStage.showAndWait();
    } catch(Exception e) {
        e.printStackTrace();
    } 
}

它看起来已经相当不错了,但我不明白的是,这两个阶段如何相互沟通?我想将一个String传递给消息中显示的对话框,当单击对话框窗口中的一个按钮时,我想对此做出相应的反应。

任何人都可以解释一下这两个阶段之间的沟通是如何运作的吗? 顺便说一句:我使用.FXML文件和控制器类。

2 个答案:

答案 0 :(得分:2)

您需要对该对话框的控制器的引用。为此,请创建FXMLLoader的实例,而不是使用静态FXMLLoader.load(URL)方法。

例如,假设您有一个班级DialogController,那么您的Dialog.fxml就像:

<AnchorPane xmlns:fx="..." fx:controller="DialogController.fxml">
...
</AnchorPane>

然后,您可以使用

访问上面DialogController方法中的delBox()
Stage dialogStage = new Stage();
FXMLLoader loader = new FXMLLoader(getClass().getResource("Dialog.fxml"));
AnchorPane root = (AnchorPane)loader.load();
DialogController controller = (DialogController) loader.getController();
Scene scene = new Scene(root);
dialogStage.setScene(scene);
dialogStage.showAndWait();

现在你可以在两个控制器之间进行通信。例如,在DialogController中,您可以定义message属性,并将其绑定到Label

public class DialogController {
    private final StringProperty message = new SimpleStringProperty("");
    public void setMessage(String message) {
        this.message.set(message);
    }
    public String getMessage() {
        return message.get();
    }
    public StringProperty messageProperty() {
        return message ;
    }

    @FXML
    private Label label ;

    public void initialize() {
        label.textProperty().bind(message);
        // ...
    }
}

然后返回你的delBox()方法:

//... as before:
        AnchorPane root = (AnchorPane)loader.load();
        DialogController controller = (DialogController) loader.getController();
        controller.setMessage("Hello World");
// ...

类似地,您可以定义在对话框本身中按下控件时设置的属性,并在showAndWait()调用之后观察它们或查询它们。

还有许多其他类似的技巧。一些例子:

https://github.com/james-d/Shared-Data-Controller/tree/master/src

https://github.com/james-d/Dialog-FXML-Example/tree/master/src

https://github.com/james-d/Nested-Controller-Example/tree/master/src/nestedcontrollerexample

答案 1 :(得分:1)

<AnchorPane xmlns:fx="..." fx:controller="DialogController.fxml">
...
</AnchorPane>
     

FX Controller是一个java文件,因此它必须是 DialogController ,并且应该包含Controller的路径,即fx:controller="applicationPackageName.DialogController"
  上面提到的fxml代码不起作用。它导致了    javafx.fxml.LoadException
  的 java.lang.InstantiationException
  的 java.lang.NoSuchMethodException

原因:jvm查找具有0个参数的类构造函数来构建实例。为了克服这个错误,需要在java中编码的函数中加载控制器文件:
loader.setController(new ControllerName(""));

总结(工作代码):
FXML文件:

<BorderPane id="background" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="240.0" prefWidth="320.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" >
    <bottom>
        <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
            <children>
                <Button onAction="#close" text="OK" />
            </children>             
        </HBox>
    </bottom>
    <center>
        <Label fx:id="messageLabel" />
    </center>
</BorderPane>

控制器文件:

public class PiPreferenceController {
     private final String message ;

        @FXML
        private Label messageLabel ;

        @FXML
        void initialize() {
            messageLabel.setText(message);
        }



        public PiPreferenceController(String message) {
            this.message = message ;
        }



        @FXML
        public void close() {
            messageLabel.getScene().getWindow().hide();
        }

}


功能:

void dialogPreferences() throws IOException {

        Stage dialogStage = new Stage();
        FXMLLoader loader = new FXMLLoader(getClass().getResource(
                "PiPreference.fxml"));

        loader.setController(new PiPreferenceController(""));
        BorderPane root = (BorderPane) loader.load();
        Scene scene = new Scene(root);
        dialogStage.setScene(scene);
        dialogStage.showAndWait();

    }