在下面简化的JavaFx程序中,它一直说Application Not Responsive。当我注释掉Platform.runLater(新的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);
}
}
答案 0 :(得分:0)
在回答之前,我想问一下你是否真的需要在Swing应用程序中嵌入JavaFX。这是两个不同的工具包,并且两者结合使用会使事情变得非常困难,特别是因为您必须管理两个不同的执行线程(AWT事件调度线程,必须在其上进行所有Swing工作)和FX Application Thread,必须进行JavaFX工作。)
假设您确实需要在Swing框架而不是JavaFX Stage中嵌入JavaFX,则需要使用SwingUtilities.invokeLater(...)
在AWT事件分派线程上创建Swing组件。需要使用Platform.runLater()
在FX Application线程上创建JavaFX控件。在您的代码中,您在主线程(而不是AWT线程)上创建和配置JFrame
并在FX应用程序线程上创建JPanel
(再次,而不是AWT线程)。我相信这会导致应用程序陷入僵局。
另一个注意事项是您的布局结构错误。您可以将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);
});
}
}