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

在应用程序中多次打开同一窗口(本例中为JavaFx),java,javafx,Java,Javafx,我有以下问题:我在应用程序中创建了菜单栏,并在应用程序中为jdbc连接配置服务器名称、用户名和密码,当选择该选项时,将显示新窗口,您可以在其中放置这些信息。但在它打开一次之后,如果我想再次打开它,我的应用程序就会显示错误。我找到了一个解决方案,但它似乎不雅观,我想知道是否有更好的方法: (这些仅是我的代码本案例的相关部分) 公共类JDBCApp扩展应用程序{ 网格连接网格; 场景连接场景; 舞台连接舞台; @凌驾 公共无效开始(阶段primaryStage){ manageMainGrid();

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

公共类JDBCApp扩展应用程序{
网格连接网格;
场景连接场景;
舞台连接舞台;
@凌驾
公共无效开始(阶段primaryStage){
manageMainGrid();
initMenuBar();
initConnectionSettingsAction();
场景=新场景(主网格,1600,1000);
scene.getStylesheets().add(JDBCApp.class.getResource(“JDBCApp.css”).toExternalForm());
初级阶段。设置标题(“申请”);
初级阶段。场景(场景);
primaryStage.show();
}
私有void initConnectionSettingsAction(){
connectionSettings.setAccelerator(KeyCombination.KeyCombination(“Ctrl+Q”));
connectionSettings.setOnAction(新的EventHandler(){
@凌驾
公共无效句柄(ActionEvent t){
manageConnectionGrid();
populateConnectionWindow();
connectionStage=新阶段();
connectionScene=新场景(connectionGrid,400240);
connectionScene.getStylesheets().add(JDBCApp.class.getResource(“JDBCApp.css”).toExternalForm());
连接阶段。设置场景(连接场景);
connectionStage.show();
}
});
}
私有void manageConnectionGrid(){
connectionGrid=新网格窗格();
connectionGrid.setId(“网格”);
对于(int i=0;i<20;i++){
connectionGrid.getColumnConstraints().add(新的ColumnConstraints(20));
如果(i<12){
connectionGrid.getRowConstraints().add(新的RowConstraints(20));
}
}
connectionGrid.setGridLinesVisible(true);
}
私有void populateConnectionWindow(){
Label giveServerName=新标签(“提供服务器地址:”);
setHalignment(给定服务器名,HPos.CENTER);
添加(给定服务器名,0,1,20,1);
final TextField serverName=new TextField();
serverName.setPrompText(SSerwer.equals(“”?“):SSerwer);
setPrefWidth(150);
setHalignment(serverName,HPos.CENTER);
add(serverName,4,2,12,1);
Label giveUserName=新标签(“用户名:”);
GridPane.setHalignment(给定用户名,HPos.CENTER);
添加(给定用户名,0,4,20,1);
最终文本字段用户名=新文本字段();
userName.setPrompText(SUserName.equals(“”?):SUserName);
userName.setPrefColumnCount(15);
setHalignment(用户名,HPos.CENTER);
添加(用户名,4,5,12,1);
Label givePassword=新标签(“密码:”);
GridPane.setHalignment(给定密码,HPos.CENTER);
添加(给定密码,0,7,20,1);
最终密码字段userPassword=新密码字段();
setPrompText(“您的密码”);
userPassword.setPrefColumnCount(15);
setHalignment(用户密码,HPos.CENTER);
add(userPassword,4,8,12,1);
按钮提交更改=新按钮(“确认更改”);
GridPane.setHalignment(提交更改,HPos.CENTER);
connectionGrid.add(提交更改,6,10,8,1);
submitChanges.setOnAction(新的EventHandler(){
@凌驾
公共无效句柄(ActionEvent t){
SSerwer=serverName.getText();
SUserName=userName.getText();
SPassword=userPassword.getText();
startConnection();
connectionGrid.getChildren().clear();
connectionStage.hide();
}
});
}
//未使用的主管道
公共静态void main(字符串[]args){
发射(args);
}
}
所以简而言之,我想知道是否有更有效的方法在窗口关闭后去掉标签和文本字段,并在每次都重新创建它们。
非常感谢您的帮助。

您的设计非常程序化。试着多考虑面向对象的问题

一组重复出现的GUI元素可能会产生一个自己的类(继承自适当的
节点
子类),构造函数会进行初始化。如果再次需要这组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();
        }
    }
}
导入javafx.application.application;
导入javafx.event.ActionEvent;
导入javafx.event.EventHandler;
导入javafx.geometry.Insets;
导入javafx.geometry.Pos;
导入javafx.scene.Node;
导入javafx.scene.scene;
导入javafx.scene.control.Button;
导入javafx.scene.control.Label;
导入javafx.scene.control.PasswordField;
导入javafx.scene.control.TextField;
导入javafx.scene.layout.HBox;
导入javafx.scene.layout.VBox;
导入javafx.stage.stage;
公共类DemoApp扩展应用程序{
公共静态void main(字符串[]args){
发射(args);
}
@凌驾
公众假期开始(阶段){
stage.setTitle(“主窗口”);
按钮OpenLoginWindows按钮=新建按钮(“打开另一个登录对话框”);
openLoginWindowButton.setOnAction(新的EventHandler(){
@凌驾
公共无效句柄(ActionEvent事件){
新登录窗口().show();
}
});
openLoginWindowButton.setPadding(
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();
        }
    }
}