JavaFX 8双重绑定单向验证

时间:2015-08-20 21:22:11

标签: binding javafx

在我的应用中,TextField双向绑定到窗格的layoutXProperty。文本字段中的任何更改都将立即更新窗格的layoutX。

例如,如果layoutX为500并且删除了最后一个零,则窗格的位置将immediatley跳转到x = 50.同样,如果窗格被拖动,则texfield中的值会反映窗格的layoutX值。

拖动'绑定很好,但现在我想在更新窗格的layoutX之前等待文本字段中的RETURN键(我想先检查有效的边界值)。我已经尝试过ChangeListeners和低级绑定,但无法令它满意地工作。

是否有人对如何实现这一点有任何想法。在我看来,这将是一个共同的行动,但在书籍或网络上有关于此的非常少的信息。 changelistener可以使用绑定事件'?

2 个答案:

答案 0 :(得分:1)

只需向更新文本字段的layoutX属性添加侦听器,并将操作事件的处理程序添加到执行验证的TextField并更新layoutX属性。如果用户按Enter键,处理程序将被触发,但之前不会。由于您不希望layoutX在文本更新时随时更新,因此此处的绑定并不合适。

SSCCE:

import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class PaneCoordinatesInTextField extends Application {

    @Override
    public void start(Stage primaryStage) {
        Label draggingLabel = createDraggingLabel();

        TextField textField = new TextField();
        draggingLabel.layoutXProperty().addListener((obs, oldLayoutX, newLayoutX) ->
            textField.setText(newLayoutX.toString()));

        textField.setOnAction(e -> {
            try {
                double x = Double.parseDouble(textField.getText());
                if (x < 0) {
                     x = 0 ;
                }
                if (x > 400) {
                    x = 400 ;
                }
                draggingLabel.setLayoutX(x);
            } catch (NumberFormatException exc) {
                textField.setText(Double.toString(draggingLabel.getLayoutX()));
            }
        });

        Pane pane = new Pane(draggingLabel);
        pane.setMinSize(600, 600);

        BorderPane root = new BorderPane(pane, textField, null, null, null);
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }

    private Label createDraggingLabel() {
        Label label = new Label("Drag me", new Rectangle(200, 200, Color.CORNFLOWERBLUE));
        label.setContentDisplay(ContentDisplay.CENTER);
        label.setTextFill(Color.WHITE);
        label.setAlignment(Pos.CENTER);

        ObjectProperty<Point2D> mouseLocation = new SimpleObjectProperty<>();
        label.setOnDragDetected(e -> mouseLocation.set(new Point2D(e.getSceneX(), e.getSceneY())));
        label.setOnMouseReleased(e -> mouseLocation.set(null));
        label.setOnMouseDragged(e -> {
            if (mouseLocation.get() == null) {
                return ;
            }
            double deltaX = e.getSceneX() - mouseLocation.get().getX();
            double deltaY = e.getSceneY() - mouseLocation.get().getY();
            label.setLayoutX(label.getLayoutX() + deltaX);
            label.setLayoutY(label.getLayoutY() + deltaY);
            mouseLocation.set(new Point2D(e.getSceneX(), e.getSceneY()));
        });
        return label;
    }

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

答案 1 :(得分:0)

我找到了'a'解决方案,但它似乎更像是一个kludge。

我将onMouseClicked和onActon处理程序附加到文本字段。

在onMouseClicked的文本字段中,我取消绑定文本字段并等待按下RETURN键。在onAction中,我使用新的文本字段值更新先前绑定的值,然后再次双向绑定它。瞧......它有效。

我可以在onAction处理程序中检查有效值。

但就像我说的那样,它似乎有点像一个极限的解决方案。有人关心评论吗?