【问题标题】:JavaFX wait until value is setJavaFX 等到值被设置
【发布时间】:2019-08-28 14:10:11
【问题描述】:

我正在努力解决以下问题: 我的 javafx 应用程序中有一个类似于弹出窗口的东西,它应该阻止应用程序,直到用户进行一些输入。它不是一个单独的阶段,我可以在其中调用 showAndWait() 然后返回阶段的输入。弹出窗口被实现为一个窗格,它被放置在其他组件之上。现在我做这样的事情:

PopupPane pp = new PopupPane()
stackPane.add(new PopupPane()); //show pane
//... waiting until user terminates popup
return pp.getInput(); //returns input when user terminates popup

所以我希望 pp.getInput() 等待,直到用户在我的弹出窗口中按下 OK/CANCEL/APPLY/... 按钮。在这种情况下,我如何才能实现类似 showAndWait() 的功能?

【问题讨论】:

  • 对于 javafx 9+ 看看这个线程:stackoverflow.com/questions/46369046/…
  • 好奇:为什么?有一些对话框/警报可以为您完成繁重的工作
  • 因为有时会出现问题,所以对话框显示在主窗口下。尤其是当我同时需要多个对话框时,在同一个窗口中“模拟”它们会更好。
  • 如果您遇到标准对话框未出现在主窗口顶部的问题,那可能是因为您在显示对话框之前没有initialize the owner
  • 然后提供一个 minimal reproducible example 来演示问题(显示在 main 下)与滚动你自己的问题(你没有显示)效果不好;)

标签: java user-interface javafx


【解决方案1】:

一种可能的方法是使用一个额外的窗格,在显示“弹出窗口”时可以禁用该窗格。

例如,假设您的Scene 的根布局窗格是StackPane。您可以将界面的所有其余部分封装在另一个 Pane 中,您可以根据需要禁用或启用。

当需要显示“弹出窗口”时,将其添加到您的StackPane 并禁用“内容”窗格。当弹出窗口关闭时,只需将其从您的 StackPane 中删除并重新启用“内容”窗格。

下面是这个概念的一个快速但公认没有吸引力的例子:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class SimulatedPopupExample extends Application {

    private static StackPane root;
    private static BorderPane content;

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

    private static void showPopup() {

        // Disable the main layout pain
        content.setDisable(true);

        VBox popup = new VBox();
        popup.setPadding(new Insets(10));
        popup.setAlignment(Pos.CENTER);
        popup.setStyle("-fx-border-color: black; -fx-background-color: -fx-base;");
        popup.setMaxSize(200, 200);

        popup.getChildren().add(
                new Button("Close Popup") {{
                    setOnAction(event -> {
                        // Re-enable the pane
                        content.setDisable(false);

                        // Remove popup from root layout
                        root.getChildren().remove(popup);

                    });
                }}
        );

        // Add popup to root layout
        root.getChildren().add(popup);
    }

    @Override
    public void start(Stage primaryStage) {

        // Simple Interface
        root = new StackPane();
        content = new BorderPane(
                new Button("Show \"Popup\"") {{
                    setOnAction(e -> showPopup());
                }},
                new Button("Top Button"),
                new Button("Right Button"),
                new Button("Bottom Button"),
                new Button("Left Button")
        );

        root.getChildren().add(content);

        // Show the stage
        primaryStage.setScene(new Scene(root));
        primaryStage.setWidth(500);
        primaryStage.setHeight(400);
        primaryStage.setTitle("SimulatedPopupExample Sample");
        primaryStage.show();

    }
}

结果:

【讨论】:

  • 我已经想通了,但还是让你失望了。但我的问题是,我需要一种方法来等待一些输入(如文本字段)。我需要在某种阻塞方法中使用它,所以我只需要调用 getInput() (在另一个类中)并等待输入
【解决方案2】:

这是一个在用户在 TextField 中输入数据之前无法关闭或接受的自定义对话框

    private void showInputTextDialog(){

            Label lblAmt = new Label("Enter Amount");
            Button btnOK = new Button("OK");
            TextField txtAmt = new TextField();

            AnchorPane customDialog = new AnchorPane();
            customDialog.setStyle("-fx-border-color:red;-fx-border-width:10px; -fx-background-color: lightblue;");
            customDialog.getChildren().addAll(lblAmt,btnOK,txtAmt);
            lblAmt.setLayoutX(30);
            lblAmt.setLayoutY(30);
            txtAmt.setLayoutX(164);
            txtAmt.setLayoutY(25);
            txtAmt.setMaxWidth(116);
            btnOK.setLayoutX(190);
            btnOK.setLayoutY(100);
            btnOK.setStyle("-fx-font-size: 18px;-fx-font-weight: bold;");
            lblAmt.setStyle("-fx-font-size: 18px;-fx-font-weight: bold;");
            txtAmt.setStyle("-fx-font-size: 18px;-fx-font-weight: bold;");

            Scene secondScene = new Scene(customDialog, 300, 180);

            EventHandler<ActionEvent> filter = event -> {
            if(txtAmt.getText().isEmpty()) {
    event.consume();
            }
            };

            // New window (Stage)
            Stage newWindow = new Stage();
            //newWindow.initStyle(StageStyle.UNDECORATED);
            newWindow.initModality(Modality.APPLICATION_MODAL);
            newWindow.setResizable(false);
            //newWindow.setTitle("Custom Dialog");
            newWindow.setScene(secondScene);
            btnOK.addEventHandler(ActionEvent.ACTION,filter);
            btnOK.setOnAction(evt -> {
            String str = txtAmt.getText();
            System.out.println("@@@@@@@@@@@@@@@@ str "+str);
            if(txtAmt.getText().trim().equals("")) {
                evt.consume();
                txtAmt.clear();
                txtAmt.requestFocus();
            }else{
                txAMT = Double.valueOf(str);
                newWindow.close();  
            }
            });

            newWindow.setOnCloseRequest(event -> {
                if(txtAmt.getText().isEmpty()) {
                event.consume();
            }
            });
            txtAmt.requestFocus();
            newWindow.showAndWait();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-13
    • 1970-01-01
    • 1970-01-01
    • 2018-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多