6

因此,我们再次将完全使用 Swing 的现有 Java 应用程序转换为使用 JavaFX。但是,该应用程序不会完全使用 JavaFX。这似乎导致警报/对话框和模式出现一些问题。我们目前使用的是 Java 8u40。

主要的应用程序基本上是在一个有菜单的 JFrame 中。主要内容窗格是 JDesktopPane,单击 MenuItem 会在 DeskopPane 中打开新的 JInternalFrames。目前,我们正在转换为 JavaFX 的屏幕基本上是 JInternalFrame 中的 JFXPanel。从 JFXPanel 打开的任何警报/对话框都是模态面板本身,但不是 JInternalFrame、DeskopPane、菜单等。

我在 DialogPane 文档中读到,他们计划在 JavaFX 的未来版本中引入一些轻量级对话框,甚至可能是 InternalFrames,所以也许我们只需要再等一会儿才能获得这个功能。但是,理想情况下,当打开一个新的警报/对话框时,它将是整个应用程序的模态。

编辑:目前为模态对话框执行以下操作:

((Stage)getDialogPane().getScene().getWindow()).setAlwaysOnTop(true);

这使得对话框总是出现在顶部,但是即使我们的主应用程序被最小化,对话框也会保持在其他应用程序的顶部。它也不会阻止框架中任何 Swing 组件的输入。

4

3 回答 3

2

您可以使用以下解决方法,它JDialog在显示时创建不可见Alert并在关闭JDialog时处理。Alert这种方法将模式扩展到整个应用程序,包括 Swing 部分。

// create Alert
Alert alert = new Alert(AlertType.INFORMATION, "Hello");

// create invisible JDialog and "show" it
JDialog dialog = new JDialog();
dialog.setModal(true);
dialog.setUndecorated(true);
dialog.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
SwingUtilities.invokeLater(() -> dialog.setVisible(true));

// show Alert
alert.showAndWait();

// close JDialog after Alert is closed
dialog.dispose();
于 2019-11-06T12:47:40.163 回答
1

我不认为我完全理解你的问题。但这是我的猜测 - 您正在尝试从一些JFXPanel模式的警报窗口(即用户将无法单击您的应用程序,直到她关闭该警报窗口)到您的整个应用程序,该应用程序部分使用 Swing 组件编写.

如果你的应用程序是用纯 JavaFX 编写的,那么你会做类似的事情(假设你在你的某处创建了一个按钮JFXPanel

button.setOnAction(evt -> {
    Alert alert = new Alert(Alert.AlertType.INFORMATION);
    alert.initModality(Modality.APPLICATION_MODAL);

    // This will not work in your code
    alert.initOwner(button.getScene().getWindow());

    alert.show();
});

但是由于initOwner需要javafx.stage.window传递摆动组件的对象在您的代码中不起作用。从 Java 8u40 开始,我认为没有正确的方法(即不是 hacks)来设置Alert对象的所有权来摆动组件。毫不奇怪,这里已经提出了这样的问题,但在撰写本文时尚未得到回答。

根据您的要求,您可以使用JOptionPane.showMessageDialog方法及其外观作为解决方法。

button.setOnAction(evt -> {
    JOptionPane.showMessageDialog(desktopPane,"My message");
});

默认情况下,这些对话框是模态的,因此无需进行任何操作。您可以从 JavaFX 组件的任何事件处理程序方法中调用它们。

于 2015-09-08T13:39:48.470 回答
1

我用一个在我的 JavaFXFrame 中实现的小接口做了一些解决方法:

public interface DialogParent {
    void setOnFocusGained(EventHandler<FocusEvent> focusHandler);
    void setOnCloseRequest(EventHandler<WindowEvent> closeHandler);
}

还有我的 JavaFXFrame 实现

public class JavaFXFrame implements DialogParent {
    private JFrame frame;
    private EventHandler<ch.irix.sumadmin.util.FocusEvent> focusGainedHandler;
    private EventHandler<javafx.stage.WindowEvent> windowClosingHandler;

public void JavaFXFrame() {
    final JFXPanel fxPanel = new JFXPanel();
    frame = new JFrame();
    frame.add(fxPanel);
    frame.addWindowListener(new WindowAdapter() {
        @Override
        public void windowClosing(WindowEvent e) {
            tryClosing(this);
        }
    });
    frame.addWindowFocusListener(new WindowAdapter() {
        @Override
        public void windowGainedFocus(WindowEvent e) {
            if (focusGainedHandler != null) {
                focusGainedHandler.handle(new FocusEvent());
            }
        }
    });
}

public void setVisible(boolean visible) {
    frame.setVisible(visible);
}

private void tryClosing(WindowListener listener) {
    javafx.stage.WindowEvent windowEvent = new javafx.stage.WindowEvent(null,    javafx.stage.WindowEvent.WINDOW_CLOSE_REQUEST);
    if (windowClosingHandler != null) {
        windowClosingHandler.handle(windowEvent);
    }
    if (!windowEvent.isConsumed()) {
        frame.setVisible(false);
    }
}

@Override
public void setOnFocusGained(EventHandler<ch.irix.sumadmin.util.FocusEvent> focusGainedHandler) {
    this.focusGainedHandler = focusGainedHandler;
}

@Override
public void setOnCloseRequest(EventHandler<javafx.stage.WindowEvent> windowClosingHandler) {
    this.windowClosingHandler = windowClosingHandler;
}

}

并显示警报:

public static void showAlert(Alert alert) {
    DialogPane dialogPane = alert.getDialogPane();
    final Stage stage = new Stage();
    stage.setScene(dialogPane.getScene());
    List<ButtonType> buttonTypes = dialogPane.getButtonTypes();
    for (ButtonType buttonType : buttonTypes) {
        ButtonBase button = (ButtonBase) dialogPane.lookupButton(buttonType);
        button.setOnAction(evt -> {
            dialogPane.setUserData(buttonType);
            stage.close();
        });
    }
    dialogParent.setOnFocusGained(event -> {
        stage.toFront();
    });
    dialogParent.setOnCloseRequest(Event::consume);
    stage.setOnCloseRequest(event -> {
        dialogParent.setOnFocusGained(null);
        dialogParent.setOnCloseRequest(null);
    });
    stage.show();
}

希望对你有帮助

于 2018-11-12T13:22:55.577 回答