使用Parent拖动上下文菜单

时间:2014-05-17 10:21:28

标签: javafx javafx-2 javafx-8

我从ContextMenu进行了这个简单的登录,它显示为验证者消息:

public class MainApp extends Application
{

    @Override
    public void start(Stage stage) throws Exception
    {
        stage.setTitle("Validation Demo");
        BorderPane borderPane = new BorderPane();

        borderPane.setCenter(loadLoginScreen());
        Scene scene = new Scene(borderPane, 700, 500);
        scene.getStylesheets().add(
            MainApp.class.getResource("/styles/context.css")
            .toExternalForm());
        stage.setScene(scene);
        stage.show();
    }

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

    private GridPane loadLoginScreen()
    {

        GridPane grid = new GridPane();
        grid.setAlignment(Pos.CENTER);
        grid.setHgap(10);
        grid.setVgap(10);
        grid.setPadding(new Insets(25, 25, 25, 25));

        Text scenetitle = new Text("Welcome");
        scenetitle.setFont(Font.font("Tahoma", FontWeight.NORMAL, 20));
        grid.add(scenetitle, 0, 0, 2, 1);

        Label userName = new Label("User Name:");
        grid.add(userName, 0, 1);

        final TextField userTextField = new TextField();
        grid.add(userTextField, 1, 1);

        Label pw = new Label("Password:");
        grid.add(pw, 0, 2);

        final PasswordField pwBox = new PasswordField();
        grid.add(pwBox, 1, 2);

        Button btn = new Button("Sign in");
        HBox hbBtn = new HBox(10);
        hbBtn.setAlignment(Pos.BOTTOM_RIGHT);
        hbBtn.getChildren().add(btn);
        grid.add(hbBtn, 1, 4);

        final Text actiontarget = new Text();
        grid.add(actiontarget, 1, 6);

        // Context Menu for error messages
        final ContextMenu usernameValidator = new ContextMenu();


        usernameValidator.setAutoHide(false);
        final ContextMenu passValidator = new ContextMenu();
        passValidator.setAutoHide(false);

        // Action on button press
        btn.setOnAction(new EventHandler<ActionEvent>()
        {

            @Override
            public void handle(ActionEvent e)
            {
                // Clearing message if any
                actiontarget.setText("");

                // Checking if the userTextField is empty
                if (userTextField.getText().equals(""))
                {
                    usernameValidator.getItems().clear();
                    usernameValidator.getItems().add(
                        new MenuItem("Please enter username Please enter username Please enter username Please enter username Please enter username"));
                    usernameValidator.show(userTextField, Side.RIGHT, 10, 0);
                }
                // Checking if the pwBox is empty
                if (pwBox.getText().equals(""))
                {
                    passValidator.getItems().clear();
                    passValidator.getItems().add(
                        new MenuItem("Please enter Password"));
                    passValidator.show(pwBox, Side.RIGHT, 10, 0);
                }
                // If both of the above textFields have values
                if (!pwBox.getText().equals("")
                    && !userTextField.getText().equals(""))
                {
                    actiontarget.setFill(Color.GREEN);
                    actiontarget.setText("Welcome");
                }
            }
        });

        userTextField.focusedProperty().addListener(
            new ChangeListener<Boolean>()
            {
                @Override
                public void changed(
                    ObservableValue<? extends Boolean> arg0,
                    Boolean oldPropertyValue, Boolean newPropertyValue)
                {
                    if (newPropertyValue)
                    {
                        // Clearing message if any
                        actiontarget.setText("");
                        // Hiding the error message
                        usernameValidator.hide();
                    }
                    }
            });

        pwBox.focusedProperty().addListener(new ChangeListener<Boolean>()
        {
            @Override
            public void changed(ObservableValue<? extends Boolean> arg0,
                Boolean oldPropertyValue, Boolean newPropertyValue)
            {
                if (newPropertyValue)
                {
                    // Clearing message if any
                    actiontarget.setText("");
                    // Hiding the error message
                    passValidator.hide();
                }
            }
        });
        return grid;
    }

}

我注意到当我拖动窗口时,不会使用父窗口拖动validatoin消息。我能以某种方式解决这个问题吗我想拖动登录表单和ContextMenu。

3 个答案:

答案 0 :(得分:1)

使用ContextMenu显示验证消息并不合适。相反,我建议使用它的兄弟节点Popup控件。

final Popup usernameValidator = new Popup();

在计算出适当的坐标后,使用其所有者控件显示它。此外,您还需要在所有者节点的本地边界的每次更改时更新此坐标。

Label mesaj = new Label("Please enter username");
mesaj.setStyle("-fx-background-color:#FCFBBD; -fx-padding: 5; -fx-border-color: #BFBD3B");
usernameValidator.getContent().add(mesaj);
userTextField.boundsInParentProperty().addListener(
        (ObservableValue<? extends Bounds> observable, Bounds oldValue, Bounds newValue) -> {
    Bounds bounds = userTextField.localToScreen(userTextField.getBoundsInLocal());
    usernameValidator.show(userTextField, bounds.getMaxX(), bounds.getMinY());
});
Bounds bounds = userTextField.localToScreen(userTextField.getBoundsInLocal());
usernameValidator.show(userTextField, bounds.getMaxX(), bounds.getMinY());

这些代码可以为您提供想法,代码重构和优化,例如方法的泛化和仅处理更改的本地边界的相关部分等。

答案 1 :(得分:1)

好的,这是一个修复。还包括Uluk的建议(仅限用户名)以使用与您的想法基本相同的弹出窗口。请注意,此修复程序不适合调整舞台大小。

public class MainApp extends Application
{
    private Popup usernameValidator;
    private ContextMenu passValidator;

    @Override
    public void start( Stage stage ) throws Exception
    {
        stage.setTitle( "Validation Demo" );
        BorderPane borderPane = new BorderPane();

        borderPane.setCenter( loadLoginScreen() );
        Scene scene = new Scene( borderPane, 700, 500 );
        scene.getStylesheets().add(MainApp.class.getResource("/styles/context.css").toExternalForm());
        stage.setScene( scene );
        stage.show();

        stage.xProperty().addListener( new ChangeListener<Number>()
        {
            @Override
            public void changed( ObservableValue<? extends Number> arg0, Number oldX, Number newX )
            {
                double delta = oldX.doubleValue() - newX.doubleValue();

                if ( usernameValidator.isShowing() ) adjustX( usernameValidator, delta );
                if ( passValidator.isShowing() ) adjustX( passValidator, delta );
            }

            private void adjustX( PopupWindow menu, double delta )
            {
                menu.setX( menu.getX() - delta );
            }
        } );

        stage.yProperty().addListener( new ChangeListener<Number>()
        {
            @Override
            public void changed( ObservableValue<? extends Number> arg0, Number oldY, Number newY )
            {
                double delta = oldY.doubleValue() - newY.doubleValue();

                if ( usernameValidator.isShowing() ) adjustY( usernameValidator, delta );
                if ( passValidator.isShowing() ) adjustY( passValidator, delta );
            }

            private void adjustY( PopupWindow menu, double delta )
            {
                menu.setY( menu.getY() - delta );
            }
        } );

        stage.focusedProperty().addListener( new ChangeListener<Boolean>()
        {
            @Override
            public void changed( ObservableValue<? extends Boolean> arg0, Boolean wasFocused, Boolean isFocused )
            {
                if ( wasFocused && ! isFocused )
                {
                    if ( usernameValidator.isShowing() ) usernameValidator.hide();
                    if ( passValidator.isShowing() ) passValidator.hide();
                }
            }
        } );

        stage.setResizable( false );
    }

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

    private GridPane loadLoginScreen()
    {
        GridPane grid = new GridPane();
        grid.setAlignment( Pos.CENTER );
        grid.setHgap( 10 );
        grid.setVgap( 10 );
        grid.setPadding( new Insets( 25, 25, 25, 25 ) );

        Text scenetitle = new Text( "Welcome" );
        scenetitle.setFont( Font.font( "Tahoma", FontWeight.NORMAL, 20 ) );
        grid.add( scenetitle, 0, 0, 2, 1 );

        Label userName = new Label( "User Name:" );
        grid.add( userName, 0, 1 );

        final TextField userTextField = new TextField();
        grid.add( userTextField, 1, 1 );

        Label pw = new Label( "Password:" );
        grid.add( pw, 0, 2 );

        final PasswordField pwBox = new PasswordField();
        grid.add( pwBox, 1, 2 );

        Button btn = new Button( "Sign in" );
        HBox hbBtn = new HBox( 10 );
        hbBtn.setAlignment( Pos.BOTTOM_RIGHT );
        hbBtn.getChildren().add( btn );
        grid.add( hbBtn, 1, 4 );

        final Text actiontarget = new Text();
        grid.add( actiontarget, 1, 6 );

        // Context Menu for error messages
        // usernameValidator = new ContextMenu();
        // usernameValidator.setAutoHide(false);
        usernameValidator = new Popup();
        passValidator = new ContextMenu();
        passValidator.setAutoHide( false );

        Label mesaj = new Label( "Please enter Username" );
        mesaj.setStyle( "-fx-background-color:#FCFBBD; -fx-padding: 5; -fx-border-color: #BFBD3B" );
        usernameValidator.getContent().add( mesaj );

        // Action on button press
        btn.setOnAction( new EventHandler<ActionEvent>()
        {
            @Override
            public void handle( ActionEvent e )
            {
                // Clearing message if any
                actiontarget.setText( "" );

                // Checking if the userTextField is empty
                if ( userTextField.getText().equals( "" ) )
                {
                    double  x, y;
                    Window  win = userTextField.getScene().getWindow();
                    x = win.getX() + userTextField.localToScene( 0, 0 ).getX() + userTextField.getScene().getX() + userTextField.getWidth();
                    y = win.getY() + userTextField.localToScene( 0, 0 ).getY() + userTextField.getScene().getY();
                    usernameValidator.show( userTextField, x, y );
                }
                // Checking if the pwBox is empty
                if ( pwBox.getText().equals( "" ) )
                {
                    passValidator.getItems().clear();
                    passValidator.getItems().add(
                            new MenuItem( "Please enter Password" ) );
                    passValidator.show( pwBox, Side.RIGHT, 10, 0 );
                }
                // If both of the above textFields have values
                if ( !pwBox.getText().equals( "" )
                        && !userTextField.getText().equals( "" ) )
                {
                    actiontarget.setFill( Color.GREEN );
                    actiontarget.setText( "Welcome" );
                }
            }
        } );

        userTextField.focusedProperty().addListener( new ChangeListener<Boolean>()
        {
            @Override
            public void changed( ObservableValue<? extends Boolean> arg0,
                    Boolean oldPropertyValue, Boolean newPropertyValue )
            {
                if ( newPropertyValue )
                {
                    // Clearing message if any
                    actiontarget.setText( "" );
                    // Hiding the error message
                    usernameValidator.hide();
                }
            }
        } );

        pwBox.focusedProperty().addListener( new ChangeListener<Boolean>()
        {
            @Override
            public void changed( ObservableValue<? extends Boolean> arg0,
                    Boolean oldPropertyValue, Boolean newPropertyValue )
            {
                if ( newPropertyValue )
                {
                    // Clearing message if any
                    actiontarget.setText( "" );
                    // Hiding the error message
                    passValidator.hide();
                }
            }
        } );

        return grid;
    }
}

答案 2 :(得分:1)

以下是两种替代且不那么复杂的方法。由于您有尺寸限制,密码版本可能更适合您的需求。

public class MainApp2 extends Application
{
    @Override
    public void start( Stage stage ) throws Exception
    {
        stage.setTitle( "Validation Demo" );
        BorderPane borderPane = new BorderPane();

        borderPane.setCenter( loadLoginScreen() );
        Scene scene = new Scene( borderPane, 700, 500 );
        scene.getStylesheets().add(MainApp.class.getResource("/styles/context.css").toExternalForm());
        stage.setScene( scene );
        stage.show();
    }

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

    private GridPane loadLoginScreen()
    {
        GridPane grid = new GridPane();
        grid.setAlignment( Pos.CENTER );
        grid.setHgap( 10 );
        grid.setVgap( 10 );
        grid.setPadding( new Insets( 25, 25, 25, 25 ) );

        Text scenetitle = new Text( "Welcome" );
        scenetitle.setFont( Font.font( "Tahoma", FontWeight.NORMAL, 20 ) );
        grid.add( scenetitle, 0, 0, 2, 1 );

        Label userName = new Label( "User Name:" );
        grid.add( userName, 0, 1 );

        final TextField userTextField = new TextField();
        grid.add( userTextField, 1, 1 );

        final Label usernameValidator = new Label("Please enter Username");
        usernameValidator.setStyle( "-fx-background-color:#FCFBBD; -fx-padding: 5; -fx-border-color: #BFBD3B" );
        usernameValidator.setVisible( false );
        usernameValidator.setManaged( false );
        grid.add( usernameValidator, 2, 1 );

        Label pw = new Label( "Password:" );
        grid.add( pw, 0, 2 );

        final PasswordField pwBox = new PasswordField();
        grid.add( pwBox, 1, 2 );

        Button btn = new Button( "Sign in" );
        HBox hbBtn = new HBox( 10 );
        hbBtn.setAlignment( Pos.BOTTOM_RIGHT );
        hbBtn.getChildren().add( btn );
        grid.add( hbBtn, 1, 4 );

        final Text actiontarget = new Text();
        grid.add( actiontarget, 1, 6 );


        // Action on button press
        btn.setOnAction( new EventHandler<ActionEvent>()
        {
            @Override
            public void handle( ActionEvent e )
            {
                // Clearing message if any
                actiontarget.setText( "" );

                // Checking if the userTextField is empty
                if ( userTextField.getText().equals( "" ) )
                {
                    usernameValidator.setVisible( true );
                    usernameValidator.setManaged( true );
                }

                // Checking if the pwBox is empty
                if ( pwBox.getText().equals( "" ) )
                {
                    pwBox.setStyle( "-fx-background-color: orangered, derive(orangered,80%); -fx-prompt-text-fill: purple;" );
                    pwBox.setPromptText( "Please enter Password" );
                }
                // If both of the above textFields have values
                if ( !pwBox.getText().equals( "" )
                        && !userTextField.getText().equals( "" ) )
                {
                    actiontarget.setFill( Color.GREEN );
                    actiontarget.setText( "Welcome" );
                }
            }
        } );

        userTextField.focusedProperty().addListener( new ChangeListener<Boolean>()
        {
            @Override
            public void changed( ObservableValue<? extends Boolean> arg0,
                    Boolean oldPropertyValue, Boolean newPropertyValue )
            {
                if ( newPropertyValue )
                {
                    // Clearing message if any
                    actiontarget.setText( "" );
                    // Hiding the error message
                    usernameValidator.setVisible( false );
                    usernameValidator.setManaged( false );
                }
            }
        } );

        pwBox.focusedProperty().addListener( new ChangeListener<Boolean>()
        {
            @Override
            public void changed( ObservableValue<? extends Boolean> arg0,
                    Boolean oldPropertyValue, Boolean newPropertyValue )
            {
                if ( newPropertyValue )
                {
                    // Clearing message if any
                    actiontarget.setText( "" );
                    // Hiding the error message
                    pwBox.setStyle( null );
                }
            }
        } );

        return grid;
    }
}