Javafx在面板中监听控件更改

时间:2016-08-19 23:21:23

标签: java javafx controls panel

我想为面板中的每个控件添加一个更改侦听器。我希望它是健壮的,所以每当我更改fxml文件时,我都不必改变监听控件更改的代码。

我已经找到了为特定类型的控件添加侦听器的方法。

panel.getChildren()
     .stream()
     .filter(node -> node instanceof TextField).forEach(node ->
            ((TextField) node).textProperty()
                .addListener((observable, oldValue, newValue) -> {
                        //execute some code
                 }));

但是我需要为我打算在面板中使用的每种类型的控件添加类似的代码。

panel.getChildren()
     .stream()
     .filter(node -> node instanceof TextField).forEach(node ->
            ((TextField) node).textProperty()
                .addListener((observable, oldValue, newValue) -> {
                        //execute some code
                 }));

panel.getChildren()
     .stream()
     .filter(node -> node instanceof TextArea).forEach(node ->
            ((TextArea) node).textProperty()
                .addListener((observable, oldValue, newValue) -> {
                        //execute some code
                 }));

//and so on...

panel.getChildren()
     .stream()
     .filter(node -> node instanceof ComboBox).forEach(node ->
            ((ComboBox<?>) node).valueProperty()
                .addListener((observable, oldValue, newValue) -> {
                        //execute some code
                 }));

我想做的是。

我有一个文档编辑器,其中有一个带控件的面板,因此每当用户更改其中一个控件预设值时,将启用带有保存和取消按钮的面板。此外,如果用户试图退出程序而不取消或保存文档,则会弹出警告,询问他是否要放弃更改并退出或取消。

但是我打算对文档结构做很多更改,所以我需要不断地从面板添加和删除控件。所以我需要一次性为面板中的每个控件添加这种类型的监听器的最佳方法。

1 个答案:

答案 0 :(得分:2)

你应该编写(扩展)你自己的控件并在你的应用程序中使用它们。在其中,您可以实现所有特定的跟踪逻辑,如@James_D所述。这样的扩展TextField应如下所示:

public class TrackableTextField extends javafx.scene.control.TextField {

    private StringProperty originalText = new ReadOnlyStringWrapper(this, "originalText");
    public final String getOriginalText() { return originalText.get(); }
    public final void setOriginalText(String value) { 
        originalText.set(value);
        setText(value);
    }
    public final StringProperty originalTextProperty() { return originalText; }

    private final ReadOnlyBooleanWrapper dirty = new ReadOnlyBooleanWrapper(this, "dirty", false);
    public final boolean isDirty() { return dirty.get(); }
    public final ReadOnlyBooleanProperty dirtyProperty() { return dirty.getReadOnlyProperty(); }

    public TrackableTextField() {
        init();
    }

    public TrackableTextField(String text) {
        init();
        setOriginalText(text);
    }

    private void init() {
        textProperty().addListener( e -> {
            dirty.set(!Objects.equals(getOriginalText(), getText()));
        } );
    }

    public void rollback() {
        setText(getOriginalText());
    }

    public void commit() {
        setOriginalText(getText());
    }
}

和用法示例可能类似

public class Test extends Application {

    private TrackableTextField tf_name = new TrackableTextField();
    private TrackableTextField tf_sname = new TrackableTextField();

    private Button save = new Button("Save");
    private Button discard = new Button("Discard");

    @Override
    public void start(Stage primaryStage) {

        GridPane root = new GridPane();

        root.add(new Label("Name: "), 0, 0);
        root.add(tf_name, 1, 0);

        root.add(new Label("Surname: "), 0, 1);
        root.add(tf_sname, 1, 1);

        root.add(save, 0, 2);
        root.add(discard, 1, 2);

        Scene scene = new Scene(root, 300, 250);

        primaryStage.setScene(scene);
        primaryStage.show();

        initialize();

    }

    private void initialize() {

        save.setDisable(true);
        discard.setDisable(true);

        save.disableProperty().bind(tf_name.dirtyProperty().or(tf_sname.dirtyProperty()).not());
        discard.disableProperty().bind(tf_name.dirtyProperty().or(tf_sname.dirtyProperty()).not());

        tf_name.setOriginalText("guleryuz");
        tf_sname.setOriginalText("guleryuz");

        save.setOnAction( e -> {
            tf_name.commit();
            tf_sname.commit();
        } );

        discard.setOnAction( e -> {
            tf_name.rollback();
            tf_sname.rollback();
        } );

    }

    public static void main(String[] args) {
        launch(args);
    }

}