简体   繁体   English

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

[英]Mixing Swing/FX: can't dispose a dialog from fxml controller

The scenario: the top-level container is a Swing JDialog which has some fx content, including a fx button that triggers a dispose of the button. 场景:顶级容器是一个Swing JDialog,它有一些fx内容,包括触发处理按钮的fx按钮。 Disposing works a expected (dialog is hidden) when the button is created and configured with the appropriate eventHandler manually. 在创建按钮并手动配置相应的eventHandler时,处理可以预期(对话框被隐藏)。 The dialog is not disposed when the button is created/configure via fxml. 通过fxml创建/配置按钮时,不会释放该对话框。 The example below contains both a manually configured and a fxml loaded/bound button to see the different behaviour. 下面的示例包含手动配置和fxml加载/绑定按钮,以查看不同的行为。

Questions: 问题:

  • anything wrong with the example? 这个例子有什么问题吗?
  • is there any difference in swing/fx interaction to be expected (manual vs. fxml)? 是否有预期的swing / fx交互有任何差异(手动与fxml)?
  • how to make it work from fxml? 如何让它从fxml工作?

The code: 代码:

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<ActionEvent>() {

            @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);
            }
        });
    }
}

The fxml content: fxml内容:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<FlowPane id="Content" fx:id="windowPanel" 
    xmlns:fx="http://javafx.com/fxml" fx:controller="fxml.DisposeExample">
    <children>
        <Button fx:id="closeButton" onAction="#onAction" 
            prefHeight="35.0" prefWidth="300.0" text="Close (fxml controller)">
        </Button>
    </children>
</FlowPane>

BTW: there's a similar question from the beginning of this year, unanswered. 顺便说一句:今年年初有一个类似的问题 ,没有答案。

Edit 编辑

something weird going on: after running for a couple of minutes, it throws a OutOfMemoryError - something deeper down doesn't stop creating .. what? 一些奇怪的事情:在运行几分钟之后,它会抛出一个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.<init>(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)

Edit 编辑

fyi: same behaviour in 8u113, so filed an issue in fx-jira , incurable optimist that I am :-) fyi:在8u113中的行为相同,所以在fx-jira提出了一个问题 ,我是无法治愈的乐观主义者:-)

anything wrong with the example? 这个例子有什么问题吗?

a resounding YES - citing Martin's (very quick and clear :-) comment to the issue: 一个响亮的 - 引用马丁(非常快速和清晰:-)评论该问题:

The problem is in your fxml file. 问题出在您的fxml文件中。

"fx:controller" attribute takes the class and creates a new instance of it (using the default contructor). “fx:controller”属性获取类并创建它的新实例(使用默认的构造函数)。 The default constructor of your DisposeExample class posts a new Runnable that will load the same fxml file again a create yet another instance of DisposeExample class. DisposeExample类的默认构造函数发布一个新的Runnable,它将再次加载相同的fxml文件,另一个创建DisposeExample类的实例。

You should either use a different class for your controller or set the controller manually using the setController() call or using a controller factory (setControllerFactory). 您应该为控制器使用不同的类,或者使用setController()调用或使用控制器工厂(setControllerFactory)手动设置控制器。 Otherwise, there is no way for FXMLLoader to know that you wanted to use your particular DisposeExample object. 否则,FXMLLoader无法知道您是否想要使用特定的DisposeExample对象。

Bug alert - remove the controller from the FXML-file and set it in the code instead. 错误警报 - 从FXML文件中删除控制器并将其设置在代码中。

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

Unfortunately this will also destroy the FX-CPU-heating on these cold days ;-) 不幸的是,这也将在这些寒冷的日子里破坏FX-CPU加热;-)

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM