1

I have following problem: I created menu bar in my application and option to configure server name, username and password for jdbc connection in my application and when option is chosen, new window is showed, where you can put those informations. 但是打开一次后,如果我想再次打开它,我的应用程序会显示错误。我找到了一个解决方案,但它似乎不优雅,我想知道是否有更好的方法来做到这一点:(这些只是我的代码案例的相关部分)

    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);
    }

}

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

4

1 回答 1

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
  • 随着应用程序的增长,您应该将这些嵌套类移动到单独的文件中
于 2013-10-29T15:56:29.200 回答