[英]JavaFx Platform.runLater Application Not Responsive
在下面的簡化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);
}
}
在回答之前,我想問一下您是否真的需要將JavaFX嵌入到Swing應用程序中。 這是兩個不同的工具包,將兩者一起使用會使事情變得非常困難,特別是因為您必須管理兩個不同的執行線程(必須在其中執行所有Swing工作的AWT事件分發線程,以及在其中必須執行所有操作的FX Application線程)。 JavaFX工作必須進行)。
假設您確實確實需要將JavaFX嵌入到Swing框架而不是JavaFX Stage中,則需要使用SwingUtilities.invokeLater(...)
在AWT事件分發線程上創建Swing組件。 需要使用Platform.runLater()
在FX Application線程上創建JavaFX控件。 在您的代碼中,您在主線程(而不是AWT線程)上創建和配置JFrame
,並在FX Application線程(同樣,不是AWT線程)上創建JPanel
。 我相信這會導致應用程序死鎖。
JFXPanel
的Javadocs中顯示了如何正確地對此進行線程化的基本概述。
另一個注意事項是您的布局結構錯誤。 您將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);
});
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.