混合Swing / FX:无法从fxml控制器处理对话框

场景:顶级容器是一个Swing JDialog,它有一些fx内容,包括触发处理按钮的fx按钮。 在创建按钮并手动配置相应的eventHandler时,处理可以预期(对话框被隐藏)。 通过fxml创建/配置按钮时,不会释放该对话框。 下面的示例包含手动配置和fxml加载/绑定按钮,以查看不同的行为。

问题:

  • 这个例子有什么问题吗?
  • 是否有预期的swing / fx交互有任何差异(手动与fxml)?
  • 如何让它从fxml工作?

代码:

package fxml; import java.io.IOException; import javafx.application.Platform; import javafx.embed.swing.JFXPanel; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.layout.FlowPane; import javax.swing.JDialog; import javax.swing.SwingUtilities; public class DisposeExample { @FXML Button closeButton; Button fxButton; private JDialog dialog; /** * The action handler method used by fx buttons. */ public void onAction(final ActionEvent ac) { SwingUtilities.invokeLater(new Runnable() { public void run() { System.out.println("onAction: " +ac); dialog.dispose(); } }); } protected Button createFxButton() { Button fxButton = new Button("close from fx"); fxButton.setOnAction(new javafx.event.EventHandler() { @Override public void handle(ActionEvent event) { onAction(event); } }); return fxButton; } public void initFX() { final JFXPanel fxPanel = new JFXPanel(); dialog.add(fxPanel); Platform.runLater(new Runnable() { @Override public void run() { FlowPane parent = null; try { parent = FXMLLoader.load(DisposeExample.class.getResource( "DisposeController.fxml")); } catch (IOException e) { e.printStackTrace(); } fxButton = createFxButton(); parent.getChildren().add(fxButton); Scene scene = new Scene(parent); fxPanel.setScene(scene); } }); } public DisposeExample() { dialog = new JDialog(); dialog.setTitle("Simple Swing Dialog"); initFX(); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { JDialog example = new DisposeExample().dialog; example.setSize(400, 400); example.setVisible(true); } }); } } 

fxml内容:

         

顺便说一句:今年年初有一个类似的问题 ,没有答案。

编辑

一些奇怪的事情:在运行几分钟后,它会抛出一个OutOfMemoryError – 更深层次的东西不会停止创建..什么?

 java.lang.OutOfMemoryError: Java heap space at java.lang.Class.getDeclaredMethods0(Native Method) at java.lang.Class.privateGetDeclaredMethods(Class.java:2521) at java.lang.Class.privateGetPublicMethods(Class.java:2641) at java.lang.Class.privateGetPublicMethods(Class.java:2657) at java.lang.Class.privateGetPublicMethods(Class.java:2657) at java.lang.Class.privateGetPublicMethods(Class.java:2657) at java.lang.Class.privateGetPublicMethods(Class.java:2657) at java.lang.Class.privateGetPublicMethods(Class.java:2657) at java.lang.Class.getMethods(Class.java:1457) at sun.reflect.misc.MethodUtil.getMethods(MethodUtil.java:99) at com.sun.javafx.fxml.BeanAdapter.updateMethodCache(BeanAdapter.java:265) at com.sun.javafx.fxml.BeanAdapter.setBean(BeanAdapter.java:250) at com.sun.javafx.fxml.BeanAdapter.(BeanAdapter.java:213) at javafx.fxml.FXMLLoader$Element.getValueAdapter(FXMLLoader.java:157) at javafx.fxml.FXMLLoader$Element.getProperties(FXMLLoader.java:165) at javafx.fxml.FXMLLoader$ValueElement.processValue(FXMLLoader.java:647) at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:570) at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2314) at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2131) at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2028) at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2744) at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2723) at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2709) at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2696) at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2685) at fxml.DisposeExample$3.run(DisposeExample.java:65) at com.sun.javafx.application.PlatformImpl$4$1.run(PlatformImpl.java:179) at com.sun.javafx.application.PlatformImpl$4$1.run(PlatformImpl.java:176) at java.security.AccessController.doPrivileged(Native Method) at com.sun.javafx.application.PlatformImpl$4.run(PlatformImpl.java:176) at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:29) 

编辑

fyi:在8u113中的行为相同,所以在fx-jira提出了一个问题 ,我是无法治愈的乐观主义者:-)

错误警报 – 从FXML文件中删除控制器并将其设置在代码中。

 FXMLLoader fxmlLoader = new FXMLLoader(DisposeExample.class.getResource("DisposeController.fxml")); fxmlLoader.setController(DisposeExample.this); parent = (FlowPane)fxmlLoader.load(); 

不幸的是,这也会在这些寒冷的日子里破坏FX-CPU加热;-)

这个例子有什么问题吗?

一个响亮的 – 引用马丁(非常快速和清晰:-)评论该问题:

问题出在您的fxml文件中。

“fx:controller”属性获取类并创建它的新实例(使用默认的构造函数)。 DisposeExample类的默认构造函数发布一个新的Runnable,它将再次加载相同的fxml文件,另一个创建DisposeExample类的实例。

您应该为控制器使用不同的类,或者使用setController()调用或使用控制器工厂(setControllerFactory)手动设置控制器。 否则,FXMLLoader无法知道您是否想要使用特定的DisposeExample对象。

那你为什么不在摇摆线上执行处理呢?