在应用程序中多次打开相同的窗口(在本例中为JavaFx)

时间:2013-10-29 13:13:18

标签: java javafx

我遇到以下问题:我在我的应用程序中创建了菜单栏,并选择在我的应用程序中配置jdbc连接的服务器名称,用户名和密码,当选择选项时,会显示新窗口,您可以在其中放置这些信息。但是在打开一次之后,如果我想再次打开它,我的应用程序会显示错误。我找到了一个解决方案,但它似乎不优雅,我想知道是否有更好的方法来做到这一点: (这些仅是我的代码的相关部分)

    public class JDBCApp extends Application {
        GridPane connectionGrid;
        Scene connectionScene;
        Stage connectionStage;

    @Override
    public void start(Stage primaryStage) {
        manageMainGrid();
        initMenuBar();
        initConnectionSettingsAction();

        Scene scene = new Scene(mainGrid, 1600, 1000);
        scene.getStylesheets().add(JDBCApp.class.getResource("JDBCApp.css").toExternalForm());
        primaryStage.setTitle("application");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void initConnectionSettingsAction() {
        connectionSettings.setAccelerator(KeyCombination.keyCombination("Ctrl+Q"));
        connectionSettings.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {

                manageConnectionGrid();

                populateConnectionWindow();

                connectionStage = new Stage();                
                connectionScene = new Scene(connectionGrid, 400, 240);
                connectionScene.getStylesheets().add(JDBCApp.class.getResource("JDBCApp.css").toExternalForm());
                connectionStage.setScene(connectionScene);
                connectionStage.show();
            }
        });
    }
    private void manageConnectionGrid() {
        connectionGrid = new GridPane();
        connectionGrid.setId("grid");
        for (int i = 0; i < 20; i++) {
            connectionGrid.getColumnConstraints().add(new ColumnConstraints(20));
            if (i < 12) {
                connectionGrid.getRowConstraints().add(new RowConstraints(20));
            }
        }
        connectionGrid.setGridLinesVisible(true);
    }

   private void populateConnectionWindow() {
        Label giveServerName = new Label("Give server adress:");
        GridPane.setHalignment(giveServerName, HPos.CENTER);
        connectionGrid.add(giveServerName, 0, 1, 20, 1);

        final TextField serverName = new TextField();
        serverName.setPromptText(SSerwer.equals("") ? "<none>" : SSerwer);
        serverName.setPrefWidth(150);
        GridPane.setHalignment(serverName, HPos.CENTER);
        connectionGrid.add(serverName, 4, 2, 12, 1);

        Label giveUserName = new Label("Username:");
        GridPane.setHalignment(giveUserName, HPos.CENTER);
        connectionGrid.add(giveUserName, 0, 4, 20, 1);

        final TextField userName = new TextField();
        userName.setPromptText(SUserName.equals("") ? "<none>" : SUserName);
        userName.setPrefColumnCount(15);
        GridPane.setHalignment(userName, HPos.CENTER);
        connectionGrid.add(userName, 4, 5, 12, 1);

        Label givePassword = new Label("Password:");
        GridPane.setHalignment(givePassword, HPos.CENTER);
        connectionGrid.add(givePassword, 0, 7, 20, 1);

        final PasswordField userPassword = new PasswordField();
        userPassword.setPromptText("Your password");
        userPassword.setPrefColumnCount(15);
        GridPane.setHalignment(userPassword, HPos.CENTER);
        connectionGrid.add(userPassword, 4, 8, 12, 1);

        Button submitChanges = new Button("Confirm changes");
        GridPane.setHalignment(submitChanges, HPos.CENTER);
        connectionGrid.add(submitChanges, 6, 10, 8, 1);

        submitChanges.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent t) {
                SSerwer = serverName.getText();
                SUserName = userName.getText();
                SPassword = userPassword.getText();
                startConnection();
                connectionGrid.getChildren().clear();
                connectionStage.hide();

            }
        });

    }

    //MAIN NOT USED
    public static void main(String[] args) {
        launch(args);
    }

}

简而言之 - 我想知道在窗口关闭后是否有更有效的方法来摆脱标签和文本字段,并且每次都会再次创建它们。 我很感激你的帮助。

1 个答案:

答案 0 :(得分:4)

您的设计非常具有程序性。尝试更多地考虑面向对象。

一组重复的GUI元素可能会导致一个自己的类(继承自适当的Node子类),构造函数正在进行初始化。如果再次需要这组GUI元素(或者一个窗口),则只需再次实例化该对象。


**编辑** 一个简单的例子:

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class DemoApp extends Application {

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

    @Override
    public void start(Stage stage) {
        stage.setTitle("Main window");
        Button openLoginWindowButton = new Button("Open another Login Dialog");
        openLoginWindowButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                new LoginWindow().show();
            }
        });
        openLoginWindowButton.setPadding(new Insets(80));
        stage.setScene(new Scene(openLoginWindowButton));
        stage.show();
    }

    class LoginWindow extends Stage {

        private LabeledTextField nameField;
        private LabeledTextField passwordField;
        private Button loginButton;

        public LoginWindow() {
            setTitle("Login");
            setScene(createScene());
            registerListeners();
        }

        private Scene createScene() {
            nameField = new LabeledTextField("Name:", false);
            passwordField = new LabeledTextField("Password:", true);
            loginButton = new Button("Submit");
            HBox bottomBox = new HBox(loginButton);
            bottomBox.setAlignment(Pos.CENTER_RIGHT);
            VBox rootBox = new VBox(20, nameField, passwordField, bottomBox);
            rootBox.setPadding(new Insets(10));
            return new Scene(rootBox);
        }

        private void registerListeners() {
            loginButton.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    System.out.println("Login attempt of " + nameField.getText());
                    ((Node) (event.getSource())).getScene().getWindow().hide();
                }
            });
            // ...
        }
    }

    class LabeledTextField extends HBox {

        private TextField textField;
        private Label label;

        public LabeledTextField(String text, boolean hideInput) {
            label = new Label(text);
            textField = hideInput ? new PasswordField() : new TextField();
            setAlignment(Pos.CENTER_RIGHT);
            setSpacing(10);
            getChildren().addAll(label, textField);
        }

        public String getText() {
            return textField.getText();
        }
    }
}
  • 您可以多次按下主窗口中的按钮以打开新的登录窗口
  • LoginWindow类继承了Stage类的所有行为并添加了一些常见组件(以这种方式实现它,您不必在重用时“重置”它们)
  • LabeledTextField演示了一个简单的复合组件,它继承自布局Node子类HBox
  • 随着应用程序的增长,您应该将这些嵌套类移动到单独的文件中