【问题标题】:JavaFx Platform.runLater Application Not ResponsiveJavaFx Platform.runLater 应用程序无响应
【发布时间】:2016-04-21 10:14:51
【问题描述】:

在以下简化的 JavaFx 程序中,它一直说 Application Not Responsive。当我注释掉 Platform.runLater(new Runnable() {...} 时,它不会崩溃。任何想法有什么问题以及如何解决它?

package apptest;

import java.awt.BorderLayout;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class apptest {


    public static JFXPanel jfxPanel = new JFXPanel();          


    public static void main(String[] args){

        final JFrame frame = new JFrame(); 


        Platform.runLater(new Runnable() {

        @Override 
        public void run() { 

        JPanel login = new JPanel();
        login.setLayout(new BorderLayout());
        login.setBounds(0, 0, 415, 180);     


        WebView webView = new WebView();
        WebEngine engine = webView.getEngine();
        engine.load("http://www.google.com");

        VBox root = new VBox(webView);
        root.setStyle( "-fx-focus-color: transparent;");
        Scene scene = new Scene(root,414,179);    

        ScrollPane scrollPane = new ScrollPane();
        scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
        scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
        scrollPane.setContent(webView);                              

        root.getChildren().addAll(scrollPane);
        jfxPanel.setScene(scene); 
        frame.add(login, BorderLayout.NORTH);
        login.add(jfxPanel, BorderLayout.NORTH);

        }

      }); 


        frame.setLayout(null);
        frame.setSize(415,180);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.setResizable(false);
        frame.setAlwaysOnTop(true);
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice defaultScreen = ge.getDefaultScreenDevice();
        Rectangle rect = defaultScreen.getDefaultConfiguration().getBounds();
        int x = 10;
        int y = (int) rect.getMaxY() - (frame.getHeight() + 50);        
        frame.setLocation(x, y);
        frame.setVisible(true); 


    }

    }

【问题讨论】:

    标签: java javafx webview


    【解决方案1】:

    在回答之前,我想问一下您是否真的需要在 Swing 应用程序中嵌入 JavaFX。这是两个不同的工具包,同时使用这两个工具包让事情变得相当困难,特别是因为您必须管理两个不同的执行线程(AWT 事件调度线程,所有 Swing 工作都必须在其上进行,而 FX 应用程序线程,所有JavaFX 工作必须进行)。

    假设您确实需要在 Swing 框架而不是 JavaFX Stage 中嵌入 JavaFX,您需要使用 SwingUtilities.invokeLater(...) 在 AWT 事件调度线程上创建 Swing 组件。 JavaFX 控件需要在 FX 应用程序线程上创建,使用 Platform.runLater()。在您的代码中,您在主线程(不是 AWT 线程)上创建和配置 JFrame,并在 FX 应用程序线程(同样,不是 AWT 线程)上创建 JPanel。我相信这会导致应用程序死锁。

    Javadocs for JFXPanel 中显示了如何正确穿线的基本大纲。

    另一个注意事项是您的布局结构是错误的。您将webView 直接添加到VBox

    VBox root = new VBox(webView);
    

    但是你将相同的webView 放在ScrollPane 中:

    scrollPane.setContent(webView);                              
    

    这会将相同的组件添加到场景图中两次,这是不允许的(无论如何也没有意义)。由于WebView 实现了自己的滚动,您可以完全省略ScrollPane

    再次假设您需要混合使用 Swing 和 JavaFX,您的应用程序代码应该如下所示

    import java.awt.BorderLayout;
    import java.awt.GraphicsDevice;
    import java.awt.GraphicsEnvironment;
    import java.awt.Rectangle;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    import javafx.application.Platform;
    import javafx.embed.swing.JFXPanel;
    import javafx.scene.Scene;
    import javafx.scene.layout.VBox;
    import javafx.scene.web.WebEngine;
    import javafx.scene.web.WebView;
    
    public class apptest {
    
    
        public static void main(String[] args) {
    
            // Create swing components on AWT thread:
    
            SwingUtilities.invokeLater(()  -> {
                final JFrame frame = new JFrame();
                JPanel login = new JPanel();
                login.setLayout(new BorderLayout());
                login.setBounds(0, 0, 415, 180);
                JFXPanel jfxPanel = new JFXPanel();
                frame.add(login, BorderLayout.NORTH);
                login.add(jfxPanel, BorderLayout.NORTH);
    
                // Create JavaFX content on FX Application Thread:
    
                Platform.runLater(new Runnable() {
    
                    @Override
                    public void run() {
    
    
                        WebView webView = new WebView();
                        WebEngine engine = webView.getEngine();
                        engine.load("http://www.google.com");
    
                        VBox root = new VBox(webView);
                        root.setStyle("-fx-focus-color: transparent;");
                        Scene scene = new Scene(root, 414, 179);
    
                        jfxPanel.setScene(scene);
    
                    }
    
                });
    
                frame.setLayout(null);
                frame.setSize(415, 180);
                frame.setLocationRelativeTo(null);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
                frame.setResizable(false);
                frame.setAlwaysOnTop(true);
                GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
                GraphicsDevice defaultScreen = ge.getDefaultScreenDevice();
                Rectangle rect = defaultScreen.getDefaultConfiguration().getBounds();
                int x = 10;
                int y = (int) rect.getMaxY() - (frame.getHeight() + 50);
                frame.setLocation(x, y);
                frame.setVisible(true);
    
    
            });
    
        }
    
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-10
      • 2017-08-10
      • 1970-01-01
      • 2014-08-16
      • 2022-07-09
      相关资源
      最近更新 更多