我遇到以下问题:我在我的应用程序中创建了菜单栏,并选择在我的应用程序中配置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);
}
}
简而言之 - 我想知道在窗口关闭后是否有更有效的方法来摆脱标签和文本字段,并且每次都会再次创建它们。 我很感激你的帮助。
答案 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