【问题标题】:Prevent multiple window And close Window when lost focus JAVAFX防止多窗口并在失去焦点时关闭窗口JAVAFX
【发布时间】:2019-01-29 00:01:23
【问题描述】:

我正在构建一个 javafx 应用程序,其中我有一个更改密码的按钮,为此我想要一个新的更改密码 FXML 加载。我知道它很简单,但我的问题是在每个按钮上单击一个新的更改密码窗口正在打开。或者有没有办法在更改密码窗口失去焦点时关闭它,即如果我点击其他任何地方。

@FXML
private void CPassBtn(ActionEvent event) {

  try 
    {
        Parent part = FXMLLoader.load(getClass().getResource("/EmpSalary/ui/Mainwin/forChangePass.fxml"));
        Stage stage = new Stage();
        stage.setResizable(false);
        stage.getIcons().add(new Image("/resources/letter.png"));
        stage.setScene(new Scene(part));

        stage.setTitle("Password change");
        stage.show();

    }
    catch (IOException ex) {
        Logger.getLogger(LoginuiController.class.getName()).log(Level.SEVERE, null, ex);
    }
}

【问题讨论】:

  • 与您的问题无关:请学习 java 命名约定并遵守它们。相关:无论是否允许打开changeDialog,您都需要一个具有布尔属性的模型层,然后将按钮的禁用绑定到该属性
  • 感谢您的指正,从现在开始我一定会遵循 java 命名约定。

标签: events javafx window project


【解决方案1】:

此解决方案检查焦点何时更改并在舞台失去焦点时关闭

public class Main extends Application {

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

    @Override
    public void start(Stage primaryStage) {
        Button button = new Button("Password Window");

        Scene scene = new Scene(button);
        primaryStage.setScene(scene);
        primaryStage.show();

        button.setOnAction(event -> System.out.println(openPasswordWindow()));
    }

    private String openPasswordWindow(){
        PasswordField passwordField = new PasswordField();
        Stage stage = new Stage(StageStyle.UTILITY);
        stage.setScene(new Scene(passwordField));
        stage.show();

        //You would need from here 
        stage.focusedProperty().addListener((ov, onHidden, onShown) -> {
            if(!stage.isFocused())
                Platform.runLater(() -> stage.close());
        });
        //Down to here

        return passwordField.getText();
    }
}

在您的代码中,它看起来像这样

@FXML
private void CPassBtn(ActionEvent event) {

    try
    {
        Parent part = FXMLLoader.load(getClass().getResource("/EmpSalary/ui/Mainwin/forChangePass.fxml"));
        Stage stage = new Stage();
        stage.setResizable(false);
        stage.getIcons().add(new Image("/resources/letter.png"));
        stage.setScene(new Scene(part));

        stage.setTitle("Password change");
        stage.show();

        stage.focusedProperty().addListener((ov, onHidden, onShown) -> {
            if(!stage.isFocused())
                Platform.runLater(() -> stage.close());
        });
    }
    catch (IOException ex) {
        Logger.getLogger(LoginuiController.class.getName()).log(Level.SEVERE, null, ex);
    }
}

【讨论】:

  • 非常感谢。和所有其他人一样,如果我在代码中犯了任何错误,我很抱歉,这是第一次使用 javafx。
【解决方案2】:

我认为这正是您正在寻找的东西

stage.focusedProperty().addListener(new ChangeListener<Boolean>()
{
  @Override
  public void changed(ObservableValue<? extends Boolean> b, Boolean oldValue, Boolean newValue)
  {
    if(newValue == false)
        stage.close();
  }
});

【讨论】:

    【解决方案3】:

    您可以使用布尔值阻止多个窗口来检查是否已加载

        private boolean stageLoaded = false ;
    
    
      @FXML private void CPassBtn(ActionEvent event) {
    
       try 
    { 
        if(stageLoaded){ return;}
        Parent part = FXMLLoader.load(getClass().getResource("/EmpSalary/ui/Mainwin/forChangePass.fxml"));
        Stage stage = new Stage();
        stage.setResizable(false);
        stage.getIcons().add(new Image("/resources/letter.png"));
        stage.setScene(new Scene(part));
    
        stage.setTitle("Password change");
        stage.show();
    
        stageLoaded = true ;
    }
    catch (IOException ex) {
        Logger.getLogger(LoginuiController.class.getName()).log(Level.SEVERE, null, ex);
    }
    }
    

    但如果您需要再次设置 stageLoaded = false 。你需要添加一个事件 stage.setOnCloseRequest

    private boolean stageLoaded = false ;
    
    
       @FXML private void CPassBtn(ActionEvent event) {
    
       try 
    { 
    if(stageLoaded){ return;}
    Parent part =FXMLLoader.load(getClass().getResource("/EmpSalary/ui/Mainwin/forChangePa 
    ss.fxml"));
    Stage stage = new Stage();
    stage.setResizable(false);
    stage.getIcons().add(new Image("/resources/letter.png"));
    stage.setScene(new Scene(part));
    
    stage.setTitle("Password change");
    stage.show();
    
    stageLoaded = true ;
     stage.setOnCloseRequest((WindowEvent even) -> {
                    stageLoaded = false;
    
    }
     catch (IOException ex) {
    Logger.getLogger(LoginuiController.class.getName()).log(Level.SEVERE, 
     null, ex);
     }
     }
    

    【讨论】:

    • 你能告诉我我做错了什么吗,拜托。特别是在我的回答中。我不知道“非常规命名”。谢谢
    【解决方案4】:

    不完全是您描述的功能,但可能使用模态会起作用(它会根据模态阻止在所有者或应用程序上处理输入事件):

    stage.initModality(Modality.WINDOW_MODAL);
    stage.initOwner(((Node) event.getSouce()).getScene().getWindow());
    stage.show();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-09
      • 1970-01-01
      • 2012-12-04
      • 1970-01-01
      • 2011-03-07
      • 1970-01-01
      相关资源
      最近更新 更多