这个想法是使用弹出的Stage
的onCloseRequestProperty属性。
当有外部请求关闭此窗口时调用。安装的事件处理程序可以通过使用收到的事件来阻止窗口关闭。
有了这个属性,你可以中断Stage
闭幕如果(被选中的一个,以免卡在你的情况下)的条件不被在WindowEvent
调用consume满足。
注:由于文档状态:它是唯一有效的,如果请求外部,所以如果你调用Stage
的close方法,附加的监听器将不执行。作为一种解决方案而不是调用此方法,您可以手动激发WindowEvent.WINDOW_CLOSE_REQUEST事件。
例子:
public class PopUpApp extends Application {
Stage popupStage;
Stage primaryStage;
@Override
public void start(Stage stage) {
try {
BorderPane root = new BorderPane();
Scene scene = new Scene(root, 400, 400);
primaryStage = stage;
initPopUpStage();
// When the Pop-Up stage is showing, do not handle any action on the
// main GUI
root.disableProperty().bind(popupStage.showingProperty());
Button b = new Button("Open deck");
b.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
// Add some ToggleButtons to simulate the cards
VBox vbox = new VBox();
vbox.setAlignment(Pos.CENTER);
List<ToggleButton> toggles = new ArrayList<ToggleButton>();
for (int i = 0; i < 4; i++) {
ToggleButton tb = new ToggleButton("Card " + i + 1);
toggles.add(tb);
}
vbox.getChildren().addAll(toggles);
Scene sc = new Scene(vbox, 300, 300);
popupStage.setScene(sc);
// On close request check for the condition
popupStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
@Override
public void handle(WindowEvent event) {
Boolean readytoClose = false;
for (ToggleButton toggle : toggles) {
if (toggle.isSelected()) {
readytoClose = true;
break;
}
}
// Consume the event a show a dialog
if (!readytoClose) {
event.consume();
Alert alert = new Alert(AlertType.INFORMATION,
"At least one card has be to be selected!");
alert.showAndWait();
}
}
});
popupStage.show();
}
});
root.setCenter(b);
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
private void initPopUpStage() {
popupStage = new Stage();
popupStage.initOwner(primaryStage);
popupStage.initStyle(StageStyle.UNDECORATED);
// On focus loss, close the window
popupStage.focusedProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
// Rather than popupStage.close(); fire the event manually
if (!newValue)
popupStage.fireEvent(new WindowEvent(popupStage, WindowEvent.WINDOW_CLOSE_REQUEST));
}
});
}
public static void main(String[] args) {
launch(args);
}
}
更新:
将主Stage
不可用我已经加入这一行:
root.disableProperty().bind(popupStage.showingProperty());
这将禁用根BorderPane
而弹出式舞台正在显示。只要弹出窗口关闭,主窗口就会再次启用。
非常感谢。我不知道我可以使用onCloseRequest来实现这种功能。尽管如此,这是一个巨大的问题。如果没有'Modality',尽管存在弹出阶段,用户仍然可以与应用程序的其余部分进行通信。他们可以点击甲板50次,并制作50个窗户。我目前的想法是在我的主要GUI类中有一个静态布尔变量,它说“是当前显示的窗口?”。如果该变量为真,则不允许在主要阶段激活任何事件处理程序。然而,这是一种痛苦。任何其他想法? – Hatefiend
请在答案中查看我的更新。 – DVarga
太棒了。最后一件事。我有六个独特的窗口将显示和隐藏像这样,我需要所有六个这样的绑定。现在,如果我调用'.bind()',它会覆盖前面的'bind',并且只有正确绑定的最后一个属性会影响禁用的属性。我怎样才能绑定多个? – Hatefiend