stage.hide() 没有关闭 window
stage.hide() doesn't close window
我有一个 JavaFX 应用程序,我创建了一个切换按钮,可以将图表弹出到新的(非模态)window。该按钮旨在将图表弹出回主应用程序 window 的 VBox
。如果手动关闭新图表window,图表也会returns到原来的VBox。
下面的代码是一个通用的 setOnAction
函数 (setToggleButton),我在初始化时为与其自己的图表关联的多个按钮调用该函数。
例如:
@Component
public class SummaryView {
private GraphService graphService;
@FXML
private VBox powerChartVBox;
@FXML
private LineChart<Number, Number> powerChart;
@FXML
private Button openPowerChart;
@FXML
private NumberAxis powerAxis;
public void setButtonToggle(Button button, LineChart<Number, Number> chart, VBox homeBox) {
var ref = new Object() {
Boolean popIn = false; // changes to allow toggle
};
button.setOnAction(actionEvent -> {
VBox windowBox = new VBox();
Stage stage = new Stage();
Scene scene = new Scene(windowBox);
stage.setOnCloseRequest(event -> {
homeBox.getChildren().add(chart);
ref.popIn = false;
button.setText("Pop Out");
});
if (!ref.popIn){
windowBox.getChildren().add(chart);
stage.setScene(scene);
stage.show();
ref.popIn = true;
button.setText("Pop In");
} else {
stage.hide(); // how to get this line to work?
homeBox.getChildren().add(chart);
ref.popIn = false;
button.setText("Pop Out");
}
});
}
@FXML
public void initialize() {
graphService = SpringContext.getBean(GraphService.class);
Platform.runLater(() -> {
setButtonToggle(openPowerChart, powerChartStage, powerChart, powerChartVBox);
// in my application I call this function a few more times on other nodes as well
});
}
@Scheduled(fixedRate = 300000)
private void updateCharts() {
Platform.runLater(() -> {
XYChart.Series<Number, Number> outputKWSeries = graphService.updateKWOutputSeries();
XYChart.Series<Number, Number> outputKVSeries = graphService.updateKVOutputSeries();
XYChart.Series<Number, Number> outputKASeries = graphService.updateKAOutputSeries();
powerAxis.setUpperBound(graphService.getUpperBound());
powerAxis.setLowerBound(graphService.getLowerBound(40));
powerChart.getData().clear();
powerChart.getData().addAll(outputKWSeries, outputKVSeries, outputKASeries);
})
}
但是,我使用“弹出”操作处理程序创建的新 window 不会从切换按钮关闭(在第一次单击后变为“弹出”,然后使用if/else 语句的第二个分支)。我尝试了各种方法,但没有找到解决方案。如果我尝试 scene.getWindow().hide()
它将导致空指针异常。我目前在下面的内容实际上不会隐藏window,只是将图表移回原来的位置。
这是屏幕截图 - 在顶部,您可以看到当我点击“弹出”按钮时留下的空白 window。
所以此刻,一切都按预期进行,但是当我按下按钮“弹出”window 时,图表 returns 回到了它的主页,但是 window保持空白打开 window。然而,使用它自己的 X 按钮手动关闭 window 会导致所需的行为,只要它还没有被切换按钮变成空白 window,在这种情况下,异常将是:
Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: Children: duplicate children added: parent = VBox[id=powerChartVBox]
这个异常对我来说很有意义,因为我在舞台上调用的 setOnCloseRequest
正试图将 VBox 添加回主应用程序的 VBox,但它已经存在于那里。
所以总而言之,如何让我的 else 分支的第一行中的 stage.hide()
在我最初创建的阶段执行,并关闭 window?
正如评论中所述,您的问题是因为您在 setOnAction
中创建了舞台。
当您切换按钮时,它会创建一个 Stage
的新实例并且不会影响已经实例化的舞台。
要解决此问题,您应该在 EventHandler
.
之外实例化 Stage
有几种方法:
public class YourController{
// Option 1
private Stage newStage = new Stage();
// Options 2 & 3
private Stage newStage;
// Option 2
public YourController(){
newStage = new Stage();
}
@FXML
public void initialize() {
// Option 3
newStage = new Stage();
// Option 4
Stage newStage = new Stage();
}
}
请注意,操作 GUI 必须在 JavaFX Application Thread
上进行,因此如果您尝试从另一个线程执行此操作,platform.runLater();
可能会派上用场。
我有一个 JavaFX 应用程序,我创建了一个切换按钮,可以将图表弹出到新的(非模态)window。该按钮旨在将图表弹出回主应用程序 window 的 VBox
。如果手动关闭新图表window,图表也会returns到原来的VBox。
下面的代码是一个通用的 setOnAction
函数 (setToggleButton),我在初始化时为与其自己的图表关联的多个按钮调用该函数。
例如:
@Component
public class SummaryView {
private GraphService graphService;
@FXML
private VBox powerChartVBox;
@FXML
private LineChart<Number, Number> powerChart;
@FXML
private Button openPowerChart;
@FXML
private NumberAxis powerAxis;
public void setButtonToggle(Button button, LineChart<Number, Number> chart, VBox homeBox) {
var ref = new Object() {
Boolean popIn = false; // changes to allow toggle
};
button.setOnAction(actionEvent -> {
VBox windowBox = new VBox();
Stage stage = new Stage();
Scene scene = new Scene(windowBox);
stage.setOnCloseRequest(event -> {
homeBox.getChildren().add(chart);
ref.popIn = false;
button.setText("Pop Out");
});
if (!ref.popIn){
windowBox.getChildren().add(chart);
stage.setScene(scene);
stage.show();
ref.popIn = true;
button.setText("Pop In");
} else {
stage.hide(); // how to get this line to work?
homeBox.getChildren().add(chart);
ref.popIn = false;
button.setText("Pop Out");
}
});
}
@FXML
public void initialize() {
graphService = SpringContext.getBean(GraphService.class);
Platform.runLater(() -> {
setButtonToggle(openPowerChart, powerChartStage, powerChart, powerChartVBox);
// in my application I call this function a few more times on other nodes as well
});
}
@Scheduled(fixedRate = 300000)
private void updateCharts() {
Platform.runLater(() -> {
XYChart.Series<Number, Number> outputKWSeries = graphService.updateKWOutputSeries();
XYChart.Series<Number, Number> outputKVSeries = graphService.updateKVOutputSeries();
XYChart.Series<Number, Number> outputKASeries = graphService.updateKAOutputSeries();
powerAxis.setUpperBound(graphService.getUpperBound());
powerAxis.setLowerBound(graphService.getLowerBound(40));
powerChart.getData().clear();
powerChart.getData().addAll(outputKWSeries, outputKVSeries, outputKASeries);
})
}
但是,我使用“弹出”操作处理程序创建的新 window 不会从切换按钮关闭(在第一次单击后变为“弹出”,然后使用if/else 语句的第二个分支)。我尝试了各种方法,但没有找到解决方案。如果我尝试 scene.getWindow().hide()
它将导致空指针异常。我目前在下面的内容实际上不会隐藏window,只是将图表移回原来的位置。
这是屏幕截图 - 在顶部,您可以看到当我点击“弹出”按钮时留下的空白 window。
所以此刻,一切都按预期进行,但是当我按下按钮“弹出”window 时,图表 returns 回到了它的主页,但是 window保持空白打开 window。然而,使用它自己的 X 按钮手动关闭 window 会导致所需的行为,只要它还没有被切换按钮变成空白 window,在这种情况下,异常将是:
Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: Children: duplicate children added: parent = VBox[id=powerChartVBox]
这个异常对我来说很有意义,因为我在舞台上调用的 setOnCloseRequest
正试图将 VBox 添加回主应用程序的 VBox,但它已经存在于那里。
所以总而言之,如何让我的 else 分支的第一行中的 stage.hide()
在我最初创建的阶段执行,并关闭 window?
正如评论中所述,您的问题是因为您在 setOnAction
中创建了舞台。
当您切换按钮时,它会创建一个 Stage
的新实例并且不会影响已经实例化的舞台。
要解决此问题,您应该在 EventHandler
.
Stage
有几种方法:
public class YourController{
// Option 1
private Stage newStage = new Stage();
// Options 2 & 3
private Stage newStage;
// Option 2
public YourController(){
newStage = new Stage();
}
@FXML
public void initialize() {
// Option 3
newStage = new Stage();
// Option 4
Stage newStage = new Stage();
}
}
请注意,操作 GUI 必须在 JavaFX Application Thread
上进行,因此如果您尝试从另一个线程执行此操作,platform.runLater();
可能会派上用场。