【问题标题】:Clojure -- how to define public mutable members using deftype?Clojure - 如何使用 deftype 定义公共可变成员?
【发布时间】:2013-05-14 05:57:53
【问题描述】:

我一直试图让 http://docs.oracle.com/javafx/2/get_started/fxml_tutorial.htm 在 clojure 中运行。

我发现通过在 java 版本中省略 @FXML 注释并将事情公开, 来自:

public class FXMLExampleController {
    @FXML private Text actiontarget; 
    @FXML protected void handleSubmitButtonAction(ActionEvent event) {
        actiontarget.setText("Sign in button pressed");
    }
} 

到:

public class FXMLExampleController {
    public Text actiontarget;  
    public void handleSubmitButtonAction(ActionEvent event) {
        actiontarget.setText("Sign in button pressed");
    }
}

...当我单击按钮时它基本上仍然有效,并且 fxml 能够访问控制器的 public Text actiontarget,其访问通常只能通过 @FXML 注释启用。

所以我试图让我的基于 clojure 的控制器类具有公共可变字段,但在过去几个小时的搜寻 :gen-class 和 deftypes 中,我找不到让它工作的方法。我能够从 java 测试代码访问final(默认)deftype 字段,但我看到的唯一在线讨论说你不能有公共和可变字段,并尝试:gen-class。好吧,我在 gen-class 中也找不到,而且我能找到的所有 gen-class 示例都只使用 clojure 中的类字段;我不确定如何在 :gen-class 中定义 :state 以便可以从 java 访问它,而且我不知道如何使它们可变和公开。

我的下一件事是尝试 clojure 注释,然后使用 fx:script 字段而不是 fx:controller 来定义 clojure 回调......但我想确保它对 deftype 或 gen- 可行/不可行先上课。

那么有人可以告诉我是否可以在 clojure 中创建一个具有公共可变字段的 java 可访问类?

谢谢。

【问题讨论】:

    标签: java clojure javafx-2 deftype gen-class


    【解决方案1】:

    不,您不能在 Clojure 中定义公共可变字段。这适用于deftypegen-class

    我想您可以尝试找出 JavaFX 是否愿意调用 getter,如果是,请在 Clojure 中定义一些 getFoo 方法。

    【讨论】:

    • 谢谢,这就是我的感觉。我突然想到也许还有其他方法可以让 fxml 通过属性、setter、getter 等与 java 对象对话,但我还没有找到那种方法。
    • 您现在可以添加相同的@FXML 注释(在撰写本文时可能无法实现)
    【解决方案2】:

    作为答案已经很晚了,但如果我发现这个问题其他人也可能...... :)

    我在 OP 中遇到了同样的问题(也就是说,我试图在 clojure 中复制 javafx 教程中的 FXML 示例),这是我的解决方案:

    1) 使用我的 FXML 中为事件驱动交互所需的所有方法创建一个接口(在我的例子中只有一个,它反映了示例中间控制器中定义的方法):

    (definterface MyFXMLControllerMethods                                                                                                                 
      (^void handleSubmitButtonAction (^javafx.event.ActionEvent event )))
    

    2) 然后使用deftype 来实例化一个实现接口的新java 类型,这很漂亮,用@FXML 注释定义一个私有可变字段:

    (deftype MyFXMLController [^{:volatile-mutable true javafx.fxml.FXML true} actiontarget]
        MyFXMLControllerMethods
            (^void handleSubmitButtonAction [this ^javafx.event.ActionEvent event]
                (.setText actiontarget "Sign in button pressed!"))
        Initializable
            (^void initialize [this ^java.net.URL location ^java.util.ResourceBundle resources]
              (assert (not= actiontarget nil)))) ; this test passes! =)
    

    正如 OP 正确指出的那样,这是允许 FXML 加载器通过自省访问控制器私有字段的关键。

    这种方法的真正好处在于,它不需要静态编译,所以除了Application class,其他一切都可以是动态的。

    其他解决方案可能涉及使用 lookup 手动初始化每个字段(有效,我尝试过)或使用自省(没有尝试过)。

    希望对你有帮助

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-27
      • 2020-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-11
      • 1970-01-01
      相关资源
      最近更新 更多