JavaFX Pop Up window 再次调用时抛出异常
JavaFX Pop Up window throws exception when called again
我目前正在尝试使用 JavaFX 在 Java 中编写一个简单的应用程序。
在应用程序中,我希望有一个弹出窗口 window 提示用户输入。只要用户不尝试再次打开弹出窗口 window,就可以正常工作。
如果他这样做,则会发生以下错误:
Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: Grid hgap=5.0, vgap=0.0, alignment=TOP_LEFTis already set as root of another scene
这是打开 window 的代码:
在主视图控制器中:
btAddChat.setOnAction(e -> lvItems.add(PopUpVC.display()));
并在弹出窗口的视图控制器中:
public class PopUpVC
{
private static final GridPane root = new GridPane();
private static final TextField tfInput = new TextField();
private static final Button btOK = new Button("OK");
private static String result;
private static Stage primaryStage = new Stage();
public static String display()
{
Scene scene = new Scene(root, 200, 50);
MainVC mvc = new MainVC();
root.setPadding(new Insets(10));
root.setHgap(5);
tfInput.setPrefWidth(scene.getWidth()*0.65);
root.add(btOK, 0, 0, 1, 1);
root.add(tfInput, 1, 0, 1, 1);
btOK.setOnAction(e ->
{
if(!tfInput.getText().equals(""))
{
primaryStage.close();
}
});
primaryStage.setResizable(false);
primaryStage.setScene(scene);
primaryStage.showAndWait();
return tfInput.getText();
}
我只复制了最重要的部分,实际错误要长很多。我知道是什么导致了错误(尝试用相同的根目录打开 window 会引发错误,因为根目录已在使用中),我只是不知道如何解决它。
这是应用程序的图片:
左上角的按钮打开弹出窗口。
弹窗:
如果有任何关于如何解决此问题的建议,我将很高兴听到他们的意见,如果有任何其他方法可以打开提示用户输入文本的弹出窗口 window,我也很高兴听到这些!
非常感谢!
OP的解决方案:
I figured it out, easy thing really, I added a parameter to the start function so when I call it I just give it a new GridPane() and it works perfectly fine.
真是错误的做法。正如@James_D 所指出的,static
对于这样的事情来说不是一个好主意。为了尽可能保持原始设计,我建议这样做,它只构建 PopUp 一次,然后重新显示它:
public class PopUp extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
Button button = new Button("Click Me");
PopUpVC popUpVC = new PopUpVC();
button.setOnAction(evt -> {
popUpVC.display();
});
primaryStage.setScene(new Scene(button));
primaryStage.show();
}
public class PopUpVC {
private final TextField tfInput = new TextField();
private Stage primaryStage = new Stage();
public PopUpVC() {
GridPane root = new GridPane();
Scene scene = new Scene(root, 200, 50);
root.setPadding(new Insets(10));
root.setHgap(5);
tfInput.prefWidthProperty().bind(scene.widthProperty().multiply(0.65));
Button btOK = new Button("OK");
root.add(btOK, 0, 0, 1, 1);
root.add(tfInput, 1, 0, 1, 1);
btOK.setOnAction(e -> {
if (!tfInput.getText().equals("")) {
primaryStage.close();
}
});
primaryStage.setResizable(false);
primaryStage.setScene(scene);
}
public String display() {
primaryStage.showAndWait();
return tfInput.getText();
}
}
}
当你有一些完全静态的东西时,比如 PopUpVC
,这暗示它只是你从其他地方移出的代码。如果您从各种其他 classes 调用方法,那么这很有用,也是一种很好的做法,这样可以节省代码重复。但是,您不应该在 class.
中将 JavaFX 元素作为静态字段
在这种情况下,您可以取消 PopUpVC
并将所有代码移动到本地方法中:
public class PopUp extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
Button button = new Button("Click Me");
button.setOnAction(evt -> {
displayPopUpVC();
});
primaryStage.setScene(new Scene(button));
primaryStage.show();
}
public String displayPopUpVC() {
TextField tfInput = new TextField();
Stage primaryStage = new Stage();
GridPane root = new GridPane();
Scene scene = new Scene(root, 200, 50);
root.setPadding(new Insets(10));
root.setHgap(5);
tfInput.prefWidthProperty().bind(scene.widthProperty().multiply(0.65));
Button btOK = new Button("OK");
root.add(btOK, 0, 0, 1, 1);
root.add(tfInput, 1, 0, 1, 1);
btOK.setOnAction(e -> {
if (!tfInput.getText().equals("")) {
primaryStage.close();
}
});
primaryStage.setResizable(false);
primaryStage.setScene(scene);
primaryStage.showAndWait();
return tfInput.getText();
}
}
这与第一个解决方案的行为略有不同,因为它不会在调用之间保留 TextField 中的文本。但如果您愿意,可以在参数中传递默认文本。
但是,正如@James_D 所指出的那样,TextInputDialog
完全符合您的要求。另外,它只用了大约 4 行代码:
public class PopUp extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
Button button = new Button("Click Me");
TextInputDialog dialog = new TextInputDialog();
dialog.setHeaderText(null);
dialog.setTitle("Chat");
dialog.setGraphic(null);
button.setOnAction(evt -> {
dialog.showAndWait();
});
primaryStage.setScene(new Scene(button));
primaryStage.show();
}
}
我目前正在尝试使用 JavaFX 在 Java 中编写一个简单的应用程序。
在应用程序中,我希望有一个弹出窗口 window 提示用户输入。只要用户不尝试再次打开弹出窗口 window,就可以正常工作。 如果他这样做,则会发生以下错误:
Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: Grid hgap=5.0, vgap=0.0, alignment=TOP_LEFTis already set as root of another scene
这是打开 window 的代码:
在主视图控制器中:
btAddChat.setOnAction(e -> lvItems.add(PopUpVC.display()));
并在弹出窗口的视图控制器中:
public class PopUpVC
{
private static final GridPane root = new GridPane();
private static final TextField tfInput = new TextField();
private static final Button btOK = new Button("OK");
private static String result;
private static Stage primaryStage = new Stage();
public static String display()
{
Scene scene = new Scene(root, 200, 50);
MainVC mvc = new MainVC();
root.setPadding(new Insets(10));
root.setHgap(5);
tfInput.setPrefWidth(scene.getWidth()*0.65);
root.add(btOK, 0, 0, 1, 1);
root.add(tfInput, 1, 0, 1, 1);
btOK.setOnAction(e ->
{
if(!tfInput.getText().equals(""))
{
primaryStage.close();
}
});
primaryStage.setResizable(false);
primaryStage.setScene(scene);
primaryStage.showAndWait();
return tfInput.getText();
}
我只复制了最重要的部分,实际错误要长很多。我知道是什么导致了错误(尝试用相同的根目录打开 window 会引发错误,因为根目录已在使用中),我只是不知道如何解决它。
这是应用程序的图片:
左上角的按钮打开弹出窗口。
弹窗:
如果有任何关于如何解决此问题的建议,我将很高兴听到他们的意见,如果有任何其他方法可以打开提示用户输入文本的弹出窗口 window,我也很高兴听到这些!
非常感谢!
OP的解决方案:
I figured it out, easy thing really, I added a parameter to the start function so when I call it I just give it a new GridPane() and it works perfectly fine.
真是错误的做法。正如@James_D 所指出的,static
对于这样的事情来说不是一个好主意。为了尽可能保持原始设计,我建议这样做,它只构建 PopUp 一次,然后重新显示它:
public class PopUp extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
Button button = new Button("Click Me");
PopUpVC popUpVC = new PopUpVC();
button.setOnAction(evt -> {
popUpVC.display();
});
primaryStage.setScene(new Scene(button));
primaryStage.show();
}
public class PopUpVC {
private final TextField tfInput = new TextField();
private Stage primaryStage = new Stage();
public PopUpVC() {
GridPane root = new GridPane();
Scene scene = new Scene(root, 200, 50);
root.setPadding(new Insets(10));
root.setHgap(5);
tfInput.prefWidthProperty().bind(scene.widthProperty().multiply(0.65));
Button btOK = new Button("OK");
root.add(btOK, 0, 0, 1, 1);
root.add(tfInput, 1, 0, 1, 1);
btOK.setOnAction(e -> {
if (!tfInput.getText().equals("")) {
primaryStage.close();
}
});
primaryStage.setResizable(false);
primaryStage.setScene(scene);
}
public String display() {
primaryStage.showAndWait();
return tfInput.getText();
}
}
}
当你有一些完全静态的东西时,比如 PopUpVC
,这暗示它只是你从其他地方移出的代码。如果您从各种其他 classes 调用方法,那么这很有用,也是一种很好的做法,这样可以节省代码重复。但是,您不应该在 class.
在这种情况下,您可以取消 PopUpVC
并将所有代码移动到本地方法中:
public class PopUp extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
Button button = new Button("Click Me");
button.setOnAction(evt -> {
displayPopUpVC();
});
primaryStage.setScene(new Scene(button));
primaryStage.show();
}
public String displayPopUpVC() {
TextField tfInput = new TextField();
Stage primaryStage = new Stage();
GridPane root = new GridPane();
Scene scene = new Scene(root, 200, 50);
root.setPadding(new Insets(10));
root.setHgap(5);
tfInput.prefWidthProperty().bind(scene.widthProperty().multiply(0.65));
Button btOK = new Button("OK");
root.add(btOK, 0, 0, 1, 1);
root.add(tfInput, 1, 0, 1, 1);
btOK.setOnAction(e -> {
if (!tfInput.getText().equals("")) {
primaryStage.close();
}
});
primaryStage.setResizable(false);
primaryStage.setScene(scene);
primaryStage.showAndWait();
return tfInput.getText();
}
}
这与第一个解决方案的行为略有不同,因为它不会在调用之间保留 TextField 中的文本。但如果您愿意,可以在参数中传递默认文本。
但是,正如@James_D 所指出的那样,TextInputDialog
完全符合您的要求。另外,它只用了大约 4 行代码:
public class PopUp extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
Button button = new Button("Click Me");
TextInputDialog dialog = new TextInputDialog();
dialog.setHeaderText(null);
dialog.setTitle("Chat");
dialog.setGraphic(null);
button.setOnAction(evt -> {
dialog.showAndWait();
});
primaryStage.setScene(new Scene(button));
primaryStage.show();
}
}