在 javafx 应用程序的 swingnode 内部使用时,JDialogs 模态行为不起作用
JDialogs Modal behaviour not working when used inside swingnode of javafx application
我有一个完整的 Java Swing 应用程序。现在我有另一个 Java-FX 应用程序。
我必须使用 Java-FX 中的 SwingNode
将 Swing 应用程序集成到 Java-FX 应用程序中。
当我这样做时,一切看起来都很好,除了 Swing 应用程序中对话框的模态行为消失了。
有什么方法可以解决此类集成中的这种行为吗?
我的 Swing 应用程序的代码片段:
class Solve extends JFrame implements ActionListener {
static JFrame f = null;
public JFrame getFrame() {
f = new JFrame("frame");
Solve s = new Solve();
JPanel p = new JPanel();
JButton b = new JButton("click");
b.addActionListener(s);
p.add(b);
f.add(p);
f.setSize(200, 200);
return f;
}
public void actionPerformed(ActionEvent e) {
String s = e.getActionCommand();
if (s.equals("click")) {
JDialog d = new JDialog(f, "dialog Box", Dialog.ModalityType.DOCUMENT_MODAL);
JLabel l = new JLabel("this is a dialog box");
d.add(l);
d.setSize(100, 100);
d.setVisible(true);
}
}
}
我的 JavaFX 应用程序的代码片段:
public class SolveJavaFX extends Application {
@Override
public void start(Stage stage) {
final SwingNode swingNode = new SwingNode();
createAndSetSwingContent(swingNode);
BorderPane pane = new BorderPane();
pane.setCenter(swingNode);
stage.setScene(new Scene(pane, 400, 450));
stage.show();
}
private void createAndSetSwingContent(final SwingNode swingNode) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Solve solve = new Solve();
swingNode.setContent((JComponent) solve.getFrame().getContentPane());
}
});
}
public static void main(String[] args) {
launch(args);
}
}
第一个问题是当您创建对话框时,您使用的是从未使用过的 JFrame。而是使用 null
.
JDialog d = new JDialog(null, "dialog Box", Dialog.ModalityType.APPLICATION_MODAL);
这对我有用。请注意,它是 APPLICATION_MODAL
而不是 DOCUMENT_MODAL
。
如果我想使用 DOCUMENT_MODAL
,那么我需要正确的 window。我已经创建了一个实用方法,可以帮助您。
Window findWindow(Container c ){
Container p = c.getParent();
while ( !(p instanceof Window )){
p = p.getParent();
}
return (Window)p;
}
现在显示对话框时。
JDialog d = new JDialog(findWindow(panel), "dialog Box", Dialog.ModalityType.DOCUMENT_MODAL);
这两者都会显示对话框,并且在对话框关闭之前不会处理对原始框架的输入。 请注意,在第二个版本中,您需要保留对 jpanel 的引用。
我认为使用 APPLICATION_MODAL
更可靠一些。 find window 应该适用于 swing 和 javafx 版本。在 openjdk11 和 openjfx11 上,SwingNode 根本不起作用。
此解决方案禁用对其他摆动组件的输入。不会禁用其他 javafx 组件。在以下示例中,javafx 按钮在显示对话框时仍会接收输入。
package sample;
import javax.swing.*;
import java.awt.event.*;
import java.awt.Dialog;
import java.awt.Window;
import java.awt.Dimension;
import java.awt.Container;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.control.Button;
import javafx.embed.swing.SwingNode;
import javafx.scene.layout.FlowPane;
import java.awt.EventQueue;
public class SolveJavaFX extends Application {
@Override
public void start(Stage stage) {
final SwingNode swingNode = new SwingNode();
createAndSetSwingContent(swingNode);
FlowPane pane = new FlowPane();
pane.getChildren().add(swingNode);
Button but = new Button("fx button");
but.setOnMouseClicked(evt->System.out.println("click!"));
pane.getChildren().add(but);
stage.setScene(new Scene(pane, 400, 450));
stage.show();
}
JPanel getPanel(){
JPanel p = new JPanel();
JButton b = new JButton("click");
b.addActionListener(evt->{
JDialog d = new JDialog(null, "dialog Box", Dialog.ModalityType.APPLICATION_MODAL);
JLabel l = new JLabel("this is a dialog box");
d.add(l);
d.setSize(100, 100);
d.setVisible(true);
} );
p.add(b);
return p;
}
private void createAndSetSwingContent(final SwingNode swingNode) {
SwingUtilities.invokeLater(() -> {
swingNode.setContent( getPanel() );
});
}
public static void main(String[] args) throws Exception {
launch(args);
}
}
我有一个完整的 Java Swing 应用程序。现在我有另一个 Java-FX 应用程序。
我必须使用 Java-FX 中的 SwingNode
将 Swing 应用程序集成到 Java-FX 应用程序中。
当我这样做时,一切看起来都很好,除了 Swing 应用程序中对话框的模态行为消失了。
有什么方法可以解决此类集成中的这种行为吗?
我的 Swing 应用程序的代码片段:
class Solve extends JFrame implements ActionListener {
static JFrame f = null;
public JFrame getFrame() {
f = new JFrame("frame");
Solve s = new Solve();
JPanel p = new JPanel();
JButton b = new JButton("click");
b.addActionListener(s);
p.add(b);
f.add(p);
f.setSize(200, 200);
return f;
}
public void actionPerformed(ActionEvent e) {
String s = e.getActionCommand();
if (s.equals("click")) {
JDialog d = new JDialog(f, "dialog Box", Dialog.ModalityType.DOCUMENT_MODAL);
JLabel l = new JLabel("this is a dialog box");
d.add(l);
d.setSize(100, 100);
d.setVisible(true);
}
}
}
我的 JavaFX 应用程序的代码片段:
public class SolveJavaFX extends Application {
@Override
public void start(Stage stage) {
final SwingNode swingNode = new SwingNode();
createAndSetSwingContent(swingNode);
BorderPane pane = new BorderPane();
pane.setCenter(swingNode);
stage.setScene(new Scene(pane, 400, 450));
stage.show();
}
private void createAndSetSwingContent(final SwingNode swingNode) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Solve solve = new Solve();
swingNode.setContent((JComponent) solve.getFrame().getContentPane());
}
});
}
public static void main(String[] args) {
launch(args);
}
}
第一个问题是当您创建对话框时,您使用的是从未使用过的 JFrame。而是使用 null
.
JDialog d = new JDialog(null, "dialog Box", Dialog.ModalityType.APPLICATION_MODAL);
这对我有用。请注意,它是 APPLICATION_MODAL
而不是 DOCUMENT_MODAL
。
如果我想使用 DOCUMENT_MODAL
,那么我需要正确的 window。我已经创建了一个实用方法,可以帮助您。
Window findWindow(Container c ){
Container p = c.getParent();
while ( !(p instanceof Window )){
p = p.getParent();
}
return (Window)p;
}
现在显示对话框时。
JDialog d = new JDialog(findWindow(panel), "dialog Box", Dialog.ModalityType.DOCUMENT_MODAL);
这两者都会显示对话框,并且在对话框关闭之前不会处理对原始框架的输入。 请注意,在第二个版本中,您需要保留对 jpanel 的引用。
我认为使用 APPLICATION_MODAL
更可靠一些。 find window 应该适用于 swing 和 javafx 版本。在 openjdk11 和 openjfx11 上,SwingNode 根本不起作用。
此解决方案禁用对其他摆动组件的输入。不会禁用其他 javafx 组件。在以下示例中,javafx 按钮在显示对话框时仍会接收输入。
package sample;
import javax.swing.*;
import java.awt.event.*;
import java.awt.Dialog;
import java.awt.Window;
import java.awt.Dimension;
import java.awt.Container;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.control.Button;
import javafx.embed.swing.SwingNode;
import javafx.scene.layout.FlowPane;
import java.awt.EventQueue;
public class SolveJavaFX extends Application {
@Override
public void start(Stage stage) {
final SwingNode swingNode = new SwingNode();
createAndSetSwingContent(swingNode);
FlowPane pane = new FlowPane();
pane.getChildren().add(swingNode);
Button but = new Button("fx button");
but.setOnMouseClicked(evt->System.out.println("click!"));
pane.getChildren().add(but);
stage.setScene(new Scene(pane, 400, 450));
stage.show();
}
JPanel getPanel(){
JPanel p = new JPanel();
JButton b = new JButton("click");
b.addActionListener(evt->{
JDialog d = new JDialog(null, "dialog Box", Dialog.ModalityType.APPLICATION_MODAL);
JLabel l = new JLabel("this is a dialog box");
d.add(l);
d.setSize(100, 100);
d.setVisible(true);
} );
p.add(b);
return p;
}
private void createAndSetSwingContent(final SwingNode swingNode) {
SwingUtilities.invokeLater(() -> {
swingNode.setContent( getPanel() );
});
}
public static void main(String[] args) throws Exception {
launch(args);
}
}