我从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。
答案 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;
}
}