【问题标题】:Simple JavaFX WebView in Java Swing app not displaying contentsJava Swing应用程序中的简单JavaFX WebView不显示内容
【发布时间】:2019-07-23 21:30:30
【问题描述】:

以下代码创建了一个 Java Swing JFrame,其中带有一个在对话框中打开 JavaFX WebView 的按钮,但是当打开时,Web 视图是空白的,而不是显示内容(URL 内容或“欢迎 JavaFX!” )。有什么问题?

(注:代码基于thisthis)。

OpenUrlInJFrameAction.java:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URI;
import java.util.Objects;

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.web.WebView;

public class OpenUrlInJFrameAction implements ActionListener {

    private final JFrame parent;
    private final URI uri;

    public OpenUrlInJFrameAction(JFrame parent, URI uri) {
        this.parent = Objects.requireNonNull(parent);
        this.uri = Objects.requireNonNull(uri);
    }

    @Override
    public void actionPerformed(ActionEvent event) {
        SwingUtilities.invokeLater(() -> {
            // You should execute this part on the Event Dispatch Thread
            // because it modifies a Swing component
            JDialog jDialog = new JDialog(parent, true);
            JFXPanel jfxPanel = new JFXPanel();
            jDialog.add(jfxPanel);
            jDialog.setSize(800, 600);
            jDialog.setLocationRelativeTo(null);
            jDialog.setVisible(true);
            // Creation of scene and future interactions with JFXPanel
            // should take place on the JavaFX Application Thread
            Platform.runLater(() -> {

                // Uncomment either the lines below Test 1 or below Test 2, 
                // both are apparently ignored by the web view.

                // Test 1
                Scene scene = createScene();
                jfxPanel.setScene(scene);                  

                // Test 2
                /*WebView webView = new WebView();
                jfxPanel.setScene(new Scene(webView));
                webView.getEngine().load(uri.toString());*/
            });
        });
    }

    private Scene createScene() {
        Group root = new Group();
        Scene scene = new Scene(root, Color.ALICEBLUE);
        Text text = new Text();

        text.setX(40);
        text.setY(100);
        text.setFont(new Font(25));
        text.setText("Welcome JavaFX!");

        root.getChildren().add(text);

        return (scene);
    }      
}

JFrameTest.java:

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Objects;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class JFrameTest extends JFrame {

    public JFrameTest(String title) {
        super(Objects.requireNonNull(title));
    }


    public static void main(String [] args) {
        SwingUtilities.invokeLater(() -> {
            JFrameTest jFrameTest = new JFrameTest("Test");
            jFrameTest.setDefaultCloseOperation(EXIT_ON_CLOSE);
            JButton jButton = new JButton("Open dialog");
            try {
                jButton.addActionListener(new OpenUrlInJFrameAction(jFrameTest,
                        new URI("https://stackoverflow.com")));
            } catch (URISyntaxException e) {
                throw new RuntimeException(e);
            }
            jFrameTest.add(jButton);
            jFrameTest.pack();
            jFrameTest.setVisible(true);
        });
    }
}

【问题讨论】:

    标签: java swing javafx javafx-webview


    【解决方案1】:

    你的例子提出了几个问题:

    • 您正在创建一个 modal 对话框,默认为ModalityType.APPLICATION_MODAL,阻止进一步的更新。相反,创建一个 modeless 对话框,如下所示。

      dialog = new JDialog(parent, Dialog.ModalityType.MODELESS);
      
    • 最佳方法取决于您的应用程序设计;但是,正如here 所讨论的,无模式 对话框可能会更加灵活;为避免重复,请在初始对话框实例上调用 toFront(),如下所示。

    • 考虑扩展AbstractAction,而不是实现ActionListener,如下图所示;注意Action 是如何重复使用的。

    • 按钮的ActionListenerevent dispatch thread 上触发;将对话创建重新排队没有必要也没有好处。

    • 覆盖getPreferredSize(),讨论过here,以建立对话框的初始空大小。

    经测试:

    import java.awt.BorderLayout;
    import java.awt.Dialog;
    import java.awt.Dimension;
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.net.URI;
    import java.net.URISyntaxException;
    import java.util.Objects;
    import javafx.application.Platform;
    import javafx.embed.swing.JFXPanel;
    import javafx.scene.Scene;
    import javafx.scene.web.WebView;
    import javax.swing.AbstractAction;
    import javax.swing.JButton;
    import javax.swing.JDialog;
    import javax.swing.JFrame;
    import static javax.swing.JFrame.EXIT_ON_CLOSE;
    import javax.swing.SwingUtilities;
    
    /**
     * @see https://stackoverflow.com/a/54958587/230513
     */
    public class JFrameTest extends JFrame {
    
        public JFrameTest(String title) {
            super(Objects.requireNonNull(title));
        }
    
        private static class OpenDialogAction extends AbstractAction {
    
            private final JFrame parent;
            private final URI uri;
            private JDialog dialog;
    
            public OpenDialogAction(JFrame parent, URI uri) {
                super.putValue(NAME, "Open " + uri.getAuthority());
                this.parent = Objects.requireNonNull(parent);
                this.uri = Objects.requireNonNull(uri);
            }
    
            @Override
            public void actionPerformed(ActionEvent event) {
                if (dialog != null) {
                    dialog.toFront();
                    return;
                }
                dialog = new JDialog(parent, Dialog.ModalityType.MODELESS);
                dialog.addWindowListener(new WindowAdapter() {
                    @Override
                    public void windowClosing(WindowEvent e) {
                        dialog = null;
                    }
                });
                dialog.setTitle(uri.getAuthority());
                JFXPanel fxPanel = new JFXPanel() {
    
                    @Override
                    public Dimension getPreferredSize() {
                        return new Dimension(640, 480);
                    }
                };
                dialog.add(fxPanel);
                dialog.pack();
                dialog.setLocationRelativeTo(null);
                dialog.setVisible(true);
                Platform.runLater(() -> {
                    WebView webView = new WebView();
                    webView.getEngine().load(uri.toString());
                    Scene scene = new Scene(webView);
                    fxPanel.setScene(scene);
                });
            }
        }
    
        public static void main(String[] args) throws URISyntaxException {
            URI uri1 = new URI("https://www.example.com");
            URI uri2 = new URI("https://www.example.net");
            URI uri3 = new URI("https://www.example.org");
            SwingUtilities.invokeLater(() -> {
                JFrameTest test = new JFrameTest("Test");
                test.setLayout(new GridLayout(0, 1));
                test.add(new JButton(new OpenDialogAction(test, uri1)));
                test.add(new JButton(new OpenDialogAction(test, uri2)));
                test.add(new JButton(new OpenDialogAction(test, uri3)));
                test.pack();
                test.setDefaultCloseOperation(EXIT_ON_CLOSE);
                test.setLocationByPlatform(true);
                test.setVisible(true);
            });
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-09-30
      • 1970-01-01
      • 1970-01-01
      • 2012-01-12
      • 1970-01-01
      • 2013-03-15
      • 1970-01-01
      • 1970-01-01
      • 2021-02-28
      相关资源
      最近更新 更多