Clojure - 如何使用deftype定义公共可变成员?

时间:2013-05-19 16:01:38

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

我一直试图让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可访问类?

感谢。

2 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:0)

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

我偶然发现了OP的同一个问题(也就是说,我试图在javafx教程中复制cloML中的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手动初始化每个字段(有效,我尝试过)或使用内省(没有尝试过)。

希望这有帮助