我们有一个主要在java 1.7
开发并在1.8
中测试的javafx应用程序。它运行正常,直到java 1.8u35
。现在我们发现,升级后JavaFx窗口不会在1.8u40
中打开。更糟糕的是,模态窗口阻止了整个标签/浏览器的使用。因此,用户只需使用任务管理器关闭浏览器即可。
我们使用javafx.embed.swing.JFXPanel
将jfx代码嵌入到swing遗留代码中。
我完全不知道可能是什么问题,因为客户端的java控制台中没有显示错误。
更新
我查看了java1.8
here的已知问题列表。我可能只能链接到我们的问题是这个错误:
BUG-RT-32597:SwingNode类不支持高DPI显示。
所以我尝试降低屏幕分辨率(1280x1024到800x600),但没有成功。
之前是否有人遇到类似的问题并知道可能会有什么帮助?
更新
我试图更好地追查问题,但没有太多运气。 为了使其更加明显,这基本上是在窗口加载时发生的事情:
public static void initWindow(JDialog dialog){
final JFXPanel jfx = new JFXPanel();
Platform.runLater(new Runnable() {
public void run() {
System.out.println("JFXPanel");
}
});
Runnable r = new Runnable() {
public void run() {
AnchorPane root = new AnchorPane;
//... do some content loading
Scene scene = new Scene(root,width,height);
System.out.println("test");
}
};
dialog.add(jfx);
System.out.println("added jfx panel.");
dialog.pack();
System.out.println("packed jfx panel.");
dialog.setLocationRelativeTo(null);
System.out.println("loaded.");
}
我认为执行会在某处停止,但它会照常运行整个函数。然而,窗户没有出现。
更新
不完全正确,我的最后评论,正如我发现的那样:
围绕上述功能,会发生以下情况:
initWindow(this); //this is extending java.swing.JDialog
System.out.println("this comment is printed to console");
super.setVisible(true); //this is not executed properly. if removed, browser will not be blocked, but window doesnt show up either
System.out.println("this comment is not printed to console";
因此,通常,JDialog会被JfxPanel打包。从JDialog类调用setVisible()方法时,应用程序被阻止但窗口不显示。实际上,在缩略图屏幕(alt + tab)中,它显示为应用程序内的容器。
删除setVisible调用时,浏览器不会被阻止,但窗口也不会显示。不幸的是,我没有找到要查找的JDialog类代码,setVisible()内部发生了什么。
任何想法,我们的设置或setVisible方法可能出错?
答案 0 :(得分:1)
我们遇到了类似的问题。在比较1.8.0_31和1.8.0_45的Java源代码时,我们发现1.8.0_45引入的JFXPanel
源代码有一些变化,可能会在以下情况下出现问题:
JDialog
初始化模态JFXPanel
(在Swing&#39的EDT上执行)JFXPanel
初始化并设置FX场景(在FX线程上执行)pack()
和show()
JDialog
(继续在EDT上阻止程序执行)JDialog
(在EDT上)后继续执行程序我们使用此工作流程以等待某个用户输入以新模态JDialog
显示,然后继续在EDT上执行正常的程序。
在1.8.0_31中,JFXPanel
的首选大小似乎在FX线程中设置,允许JDialog.pack()
确定正确的边界。
在1.8.0_45中,JFXPanel的首选大小似乎不再设置在FX线程中,而是在执行所有挂起的AWT事件后在EDT中设置。因此,当执行(4)时,JDialog.pack()
不知道场景的首选大小。因此,对话框没有内容,或者如果未修饰则不显示,如上述原始问题中所述。
以下是重现不同行为的完整示例:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// create JDialog on EDT
final JDialog dialog = new JDialog((JDialog)null, "JDialog");
// initialize FX platform and create JFXPanel
final JFXPanel jfxPanel = new JFXPanel();
// add resize listener for JFXPanel
jfxPanel.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
// not called in 1.8.0_45
System.out.println("JFXPanel.getSize(): "+jfxPanel.getSize());
}
});
// set FX Scene on JFXPanel and wait until finished
runAndWait(new Runnable() {
public void run() {
Text text = TextBuilder.create().text("JavaFx content").y(20).build();
Group root = new Group(text);
Scene scene = new Scene(root);
jfxPanel.setScene(scene);
}
});
// show undecorated modal JDialog with FX content
System.out.println("JFXPanel.getPreferredSize(): "+jfxPanel.getPreferredSize());
dialog.setUndecorated(true);
dialog.add(jfxPanel);
dialog.pack();
dialog.setModal(true);
System.out.println("JDialog.setVisible()");
dialog.setVisible(true);
}
});
}
private static void runAndWait(Runnable r) {
try {
FutureTask<Object> task = new FutureTask<Object>(r, null);
Platform.runLater(task);
task.get();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
运行此程序时,componentResized()
仅在1.8.0_31中调用,但不在1.8.0_45中调用。
在EDT上保持同步程序工作流程时可能的解决方法是将JDialog.pack()
替换为JDialog.setSize(...)
,e。 G。通过设置一个恒定的大小或使用可以使用root.getBoundsInLocal()
确定的FX场景的大小。
答案 1 :(得分:0)
我遇到了@Peter使用1.8.0_121描述的相同行为。
我能够使用窗口监听器使dialog.pack()工作。
dialog.addWindowListener( new WindowAdapter() {
@Override
public void windowOpened(WindowEvent e) {
((JDialog)e.getSource()).pack();
}
});