【发布时间】:2015-11-27 00:44:23
【问题描述】:
当我在面板中有多个 SwingNode(JFXPanel 中的 GridPane)时,我注意到性能极度下降。如果只有一个 SwingNode,这似乎不会发生。
我意识到在混合 Swing 和 JavaFX 时会出现一些预期的降级,但这会使应用程序几乎无法使用(而且我无法真正改变我的行业环境;遗留代码仍在 Swing 中,但我们真的想要新的JavaFX 图形实用程序)。
这是在 Java 8u60 上的 Windows 7 上运行的。
MCVE:
import javax.swing.*;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.embed.swing.SwingNode;
import javafx.scene.Scene;
import javafx.scene.control.ToggleButton;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
public class SwingNodeTest {
private static Scene createScene(JComponent button1, JComponent button2) {
GridPane pane = new GridPane();
pane.getColumnConstraints().add(new ColumnConstraints(100));
pane.getColumnConstraints().add(new ColumnConstraints(200));
SwingNode node1 = new SwingNode();
// Best practice to call SwingNode->setContent(...) on the EDT, but doesn't make
// a difference for the test.
node1.setContent(button1);
pane.add(node1, 0, 0);
ToggleButton node2 = new ToggleButton("2");
// Commenting out the above line and uncommenting the below lines cause EXTREME
// Performance degradation.
// SwingNode node2 = new SwingNode();
// node2.setContent(button2);
pane.add(node2, 1, 0);
return new Scene(pane);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
JFXPanel panel = new JFXPanel();
frame.setSize(800, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(panel);
frame.setVisible(true);
JButton button1 = new JButton("1");
JToggleButton button2 = new JToggleButton("2");
Platform.runLater(new Runnable() {
@Override
public void run() {
final Scene scene = createScene(button1, button2);
panel.setScene(scene);
}
});
}
});
}
}
编辑:让这个 MCVE 运行几分钟后才意识到,我得到了 OutOfMemoryErrors(超出了 GC 开销限制)。
【问题讨论】:
-
它看起来像一个带有嵌入式
JFXPanel的JFrame和嵌入式SwingNode对象会导致此问题。使用 Eclipse MAT 和-XX:+HeapDumpOnOutOfMemoryError我看到 JavaFX 事件调度队列变得巨大。但是,如果我重新编写代码以使用 JavaFXApplication,并摆脱JFrame和JFXPanel,那么一切都很好。你有这种可能吗? -
我正在开发的软件对 Swing 进行了大量投资。将软件彻底改造为 JavaFX 是不可行的,至少在短期内是不可行的。
-
在 JavaFX 中包装应用程序可能更可行(即:在 SwingNode 中将 Swing 应用程序作为 JavaFX 应用程序启动)。似乎这不太可能解决问题;而不是包含包含 Swing 的 JavaFX 的 Swing,而是包含包含 Swing 的 JavaFX 的 JavaFX,我无法想象它会更好。等我到办公室再测试一下。
-
在考虑了我办公室的软件情况后,我意识到包装应用程序在短期内也不可行(框架实际上是由我的外部软件加载的)团队/项目)。我可能暂时坚持使用 JFrame 作为顶级容器。
-
进行分析时,直到 Swing 组件获得焦点才会出现问题。