JavaFx/ Swing window 更新到 Java 1.8u40 后打不开
JavaFx/ Swing window does not open after update to Java 1.8u40
我们有一个主要在 java 1.7
开发并在 1.8
测试的 javafx 应用程序。在 java 1.8u35
之前 运行 还好。现在我们发现,升级后 JavaFx windows 将不会在 1.8u40
中打开。更糟糕的是,模态 windows 会阻止使用整个选项卡/浏览器。所以用户只能使用任务管理器关闭浏览器。
我们使用 javafx.embed.swing.JFXPanel
将 jfx 代码嵌入到 swing 遗留代码中。
我完全不知道可能是什么问题,因为客户端的 java 控制台中没有显示任何错误。
更新:
我查看了 java1.8
here 的已知问题列表。对于我们的问题,我唯一可能 link 就是这个错误:
BUG-RT-32597: The SwingNode class does not support High DPI displays.
所以我尝试降低屏幕分辨率(1280x1024 到 800x600)但没有成功。
有没有人以前遇到过类似的问题并且知道什么可以帮助?
更新:
我试图更好地找出问题所在,但运气不佳。
为了让它更显眼,这基本上就是 window loading:
上发生的事情
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.");
}
我以为执行会在某个地方停止,但 运行 整个函数照常执行。然而 window 没有出现。
更新:
不完全正确,我最后的评论,正如我发现的那样:
围绕上述函数,会发生以下情况:
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 class 调用 setVisible() 方法时,应用程序被阻止但 window 未显示。实际上,在缩略图屏幕 (alt+tab) 中,它显示为应用程序内部的容器。
删除 setVisible 调用时,浏览器不会被阻止,而且 window 也不会显示。不幸的是,我没有找到 JDialog class 代码来查找,setVisible().
内部发生了什么
任何想法,我们的设置或 setVisible 方法可能有什么问题?
我们遇到了类似的问题。在比较 1.8.0_31 和 1.8.0_45 的 Java 源代码时,我们发现 1.8.[=54= 引入的 JFXPanel
源代码有一些变化。 ] 在以下情况下可能会出现问题:
- 用
JFXPanel
初始化模态JDialog
(在Swing的EDT上执行)
- 在 FX 任务(在 FX 线程上执行)
JFXPanel
上初始化并设置 FX 场景
- 等待 FX 任务完成(等待 EDT)
pack()
和 show()
JDialog
(美国东部时间继续,阻止程序执行)
- 在用户关闭后继续执行程序
JDialog
(美国东部时间)
我们使用此工作流程是为了等待一些用户输入以新模式显示 JDialog
并在之后继续在 EDT 上正常执行程序。
在 1.8.0_31 中,JFXPanel
的首选大小似乎是在允许 JDialog.pack()
确定正确边界的 FX 线程中设置的。
在 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(...)
,例如。 G。通过设置恒定大小或使用可以使用 root.getBoundsInLocal()
.
确定的 FX 场景的大小
我遇到了@Peter 使用 1.8 描述的相同行为。0_121。
我能够使用 window 侦听器让 dialog.pack() 工作。
dialog.addWindowListener( new WindowAdapter() {
@Override
public void windowOpened(WindowEvent e) {
((JDialog)e.getSource()).pack();
}
});
我们有一个主要在 java 1.7
开发并在 1.8
测试的 javafx 应用程序。在 java 1.8u35
之前 运行 还好。现在我们发现,升级后 JavaFx windows 将不会在 1.8u40
中打开。更糟糕的是,模态 windows 会阻止使用整个选项卡/浏览器。所以用户只能使用任务管理器关闭浏览器。
我们使用 javafx.embed.swing.JFXPanel
将 jfx 代码嵌入到 swing 遗留代码中。
我完全不知道可能是什么问题,因为客户端的 java 控制台中没有显示任何错误。
更新:
我查看了 java1.8
here 的已知问题列表。对于我们的问题,我唯一可能 link 就是这个错误:
BUG-RT-32597: The SwingNode class does not support High DPI displays.
所以我尝试降低屏幕分辨率(1280x1024 到 800x600)但没有成功。
有没有人以前遇到过类似的问题并且知道什么可以帮助?
更新:
我试图更好地找出问题所在,但运气不佳。 为了让它更显眼,这基本上就是 window loading:
上发生的事情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.");
}
我以为执行会在某个地方停止,但 运行 整个函数照常执行。然而 window 没有出现。
更新:
不完全正确,我最后的评论,正如我发现的那样:
围绕上述函数,会发生以下情况:
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 class 调用 setVisible() 方法时,应用程序被阻止但 window 未显示。实际上,在缩略图屏幕 (alt+tab) 中,它显示为应用程序内部的容器。
删除 setVisible 调用时,浏览器不会被阻止,而且 window 也不会显示。不幸的是,我没有找到 JDialog class 代码来查找,setVisible().
内部发生了什么任何想法,我们的设置或 setVisible 方法可能有什么问题?
我们遇到了类似的问题。在比较 1.8.0_31 和 1.8.0_45 的 Java 源代码时,我们发现 1.8.[=54= 引入的 JFXPanel
源代码有一些变化。 ] 在以下情况下可能会出现问题:
- 用
JFXPanel
初始化模态JDialog
(在Swing的EDT上执行) - 在 FX 任务(在 FX 线程上执行)
JFXPanel
上初始化并设置 FX 场景 - 等待 FX 任务完成(等待 EDT)
pack()
和show()
JDialog
(美国东部时间继续,阻止程序执行)- 在用户关闭后继续执行程序
JDialog
(美国东部时间)
我们使用此工作流程是为了等待一些用户输入以新模式显示 JDialog
并在之后继续在 EDT 上正常执行程序。
在 1.8.0_31 中,JFXPanel
的首选大小似乎是在允许 JDialog.pack()
确定正确边界的 FX 线程中设置的。
在 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(...)
,例如。 G。通过设置恒定大小或使用可以使用 root.getBoundsInLocal()
.
我遇到了@Peter 使用 1.8 描述的相同行为。0_121。
我能够使用 window 侦听器让 dialog.pack() 工作。
dialog.addWindowListener( new WindowAdapter() {
@Override
public void windowOpened(WindowEvent e) {
((JDialog)e.getSource()).pack();
}
});