因此,我们再次将使用完全Swing的现有Java应用程序转换为使用JavaFX。但是,该应用程序将不会完全使用JavaFX。这似乎导致了警报/对话和模态的一些问题。我们目前正在使用Java 8u40。
主应用程序基本上是一个带有菜单的JFrame。主内容窗格是JDesktopPane,单击MenuItem会在DeskopPane中打开新的JInternalFrame。我们转换为JavaFX的屏幕目前基本上是JInternalFrame中的JFXPanel。从JFXPanel打开的任何警报/对话框都是面板本身的模态,但不是JInternalFrame,DeskopPane,Menu等。
我在DialogPane文档中读到他们计划在JavaFX的未来版本中引入一些轻量级对话框甚至可能是InternalFrames,所以我们可能只需要等待一段时间才能实现这一功能。但是,理想情况下,当打开一个新的警报/对话框时,它将是整个应用程序的模态。
编辑: 目前正在对模态对话框执行以下操作:
((Stage)getDialogPane().getScene().getWindow()).setAlwaysOnTop(true);
这使对话框始终显示在顶部,但即使我们的主应用程序已最小化,对话框也会保留在其他应用程序之上。它也不会阻止对帧中任何Swing组件的输入。
答案 0 :(得分:2)
我认为我完全理解你的问题。但这是我的猜测 - 您正在尝试从某些JFXPanel
创建一个警告窗口,该窗口将是模态的(即,用户将无法在您的应用程序中单击,直到她关闭该警报窗口)到您的整个应用程序,这是部分使用摆动组件书写。
如果您的应用程序是用纯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
要求传递swing组件的javafx.stage.window
对象在您的代码中不起作用。从Java 8u40开始,我认为没有正确的方法(即不是黑客)将Alert
个对象的所有权设置为swing组件。毫不奇怪,这些问题已被提出here,并且在写这篇文章时没有回答。
根据您的要求,您可以使用JOptionPane.showMessageDialog
方法及其外观作为解决方法。
button.setOnAction(evt -> {
JOptionPane.showMessageDialog(desktopPane,"My message");
});
默认情况下,这些对话框是模态的,因此无需任何工作。您可以从JavaFX组件的任何事件处理程序方法中调用它们。
答案 1 :(得分: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();
}
希望这对您有帮助
答案 2 :(得分:1)
您可以使用以下变通办法,在显示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();