JavaFX FXML 对话框 - 无法使用 X 按钮关闭它

标签 java javafx fxml

我预计将完成一个 JavaFX 对话框。我将 Controller 类添加到准备好的 FXML

<?xml version="1.0" encoding="UTF-8"?>

<?import java.net.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.image.Image?>


<Dialog fx:id="dialog"
    fx:controller="myapp.AddDialogController"
    xmlns:fx="http://javafx.com/fxml">
    <dialogPane>
        <DialogPane prefWidth="400.0" prefHeight="300.0">
            <stylesheets>
                <URL value="@/css/styles.css" />
            </stylesheets>
            <content>
                <VBox>
                    <Label text="Add some content here..."></Label>
                </VBox>
            </content>
        </DialogPane>
    </dialogPane>
</Dialog>

现在,当我尝试使用桌面环境提供的 X 按钮关闭对话框时,没有任何反应。我做错了什么?

最佳答案

解决方案 - 将按钮添加到对话框

查看答案:

I also recommend setting at least a CANCEL_CLOSE button or OK_DONE button in your JavaFX Alert, otherwise the user may have a difficult time actually closing the alert as the dialog will probably not respond to key presses as the user expects.

尝试使用窗口框架中操作系统的 X 按钮来关闭舞台可能也是如此。

背景信息

要进一步了解该行为,请阅读 Dialog javadoc 中的对话框关闭规则。 :

It is important to understand what happens when a Dialog is closed, and also how a Dialog can be closed, especially in abnormal closing situations (such as when the 'X' button is clicked in a dialogs title bar, or when operating system specific keyboard shortcuts (such as alt-F4 on Windows) are entered). Fortunately, the outcome is well-defined in these situations, and can be best summarised in the following bullet points:

  • JavaFX dialogs can only be closed 'abnormally' (as defined above) in two situations:
    1. When the dialog only has one button, or
    2. When the dialog has multiple buttons, as long as one of them meets one of the following requirements:
      1. The button has a ButtonType whose ButtonBar.ButtonData is of type ButtonBar.ButtonData.CANCEL_CLOSE.
      2. The button has a ButtonType whose ButtonBar.ButtonData returns true when ButtonBar.ButtonData.isCancelButton() is called.
  • In all other situations, the dialog will refuse to respond to all close requests, remaining open until the user clicks on one of the available buttons in the DialogPane area of the dialog.
  • If a dialog is closed abnormally, and if the dialog contains a button which meets one of the two criteria above, the dialog will attempt to set the result property to whatever value is returned from calling the result converter with the first matching ButtonType.
  • If for any reason the result converter returns null, or if the dialog is closed when only one non-cancel button is present, the result property will be null, and the showAndWait() method will return Optional.empty(). This later point means that, if you use either of option 2 or option 3 (as presented earlier in this class documentation), the Optional.ifPresent(java.util.function.Consumer) lambda will never be called, and code will continue executing as if the dialog had not returned any value at all.

所以,如果对话框中没有按钮,它就无法关闭...

回答后续问题

And can I set the button type from FXML?

也许吧,我不知道,我从来没有尝试过。无论如何我不会建议它,相反我建议只从代码中设置按钮类型。老实说,我可能只会在 FXML 中定义对话框的内容 Pane (例如,仅 FXML 的 VBox 部分及其子元素),并将其余的封闭对话框定义保留在 Java 代码中。我很惊讶在 FXML 中定义对话框甚至可以工作,但它确实有效:-) 但是,您无法使用对话框作为 SceneBuilder 中的根 XML 元素打开 FXML(并且使用 SceneBuilder 定义 UI 的能力是 IMO 之一)首先是使用 FXML 的最佳理由)。

示例解决方案

以下是对话框的对话框定义示例,可以通过对话框中的按钮或组合键或单击操作系统提供的对话框框架中的关闭图标来关闭该对话框:

AddDialogController.java

package myapp.ui;

public class AddDialogController {}

DialogDisplayApp.java

package myapp.ui;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.io.IOException;

public class DialogDisplayApp extends Application {

    @Override
    public void start(Stage stage) throws IOException {
        FXMLLoader loader = new FXMLLoader(
                getClass().getResource(
                        "add-dialog.fxml"
                )
        );

        stage.setScene(new Scene(new VBox(new Label("Main Window")), 600, 400));
        stage.show();

        Dialog dialog = loader.load();
        dialog.getDialogPane().getButtonTypes().addAll(
                ButtonType.CLOSE
        );

        dialog.initOwner(stage);
        dialog.showAndWait();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

myapp/ui/add-dialog.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Dialog?>
<?import javafx.scene.control.DialogPane?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.VBox?>
<Dialog fx:id="dialog"
        fx:controller="myapp.ui.AddDialogController"
        xmlns:fx="http://javafx.com/fxml">
  <dialogPane>
    <DialogPane prefWidth="400.0" prefHeight="300.0">
      <content>
        <VBox>
          <Label text="Add some content here..."></Label>
        </VBox>
      </content>
    </DialogPane>
  </dialogPane>
</Dialog>

关于JavaFX FXML 对话框 - 无法使用 X 按钮关闭它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37619885/

相关文章:

JAVA 编译器 API - 无法找到外部类文件

java - 无法在 JavaFX 中加载图像

java - 如何使 JavaFX 对象出现在 FXML 中?

javafx - FXML <opaqueInsets> 标签

JavaFX动态添加按钮

java - 如何使用 Spring Data JPA 发出修改查询以通过其 ID 删除一组实体?

具有反向引用的 Java 正则表达式交集

java - 在 Lollipop 上隐藏系统 UI

javafx - 将 Outlook 电子邮件拖到 JavaFX 应用程序中

javascript - 将 Javascript 上调到 JavaFX