2013-05-19 2 views
2

Я пытался получить http://docs.oracle.com/javafx/2/get_started/fxml_tutorial.htm работает в clojure.Clojure - как определить public mutable members, используя deftype?

я обнаружил, что, опуская @FXML аннотаций в версии Java и делать вещи, общественные от:

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 сможет добраться доконтроллера, доступ к которому обычно разрешен только с помощью аннотации @FXML.

Таким образом, я пытаюсь сделать свой класс контроллера на основе clojure общедоступными изменяемыми полями, но в последние несколько часов охоты через gen-class и deftypes я не могу найти способ заставить его работать. Мне удалось получить доступ к final (по умолчанию) полям deftype из тестового кода Java, но единственное онлайн-обсуждение, которое я видел, говорит о том, что у вас не может быть общедоступных и изменяемых полей и попробовать gen-class. Ну, я не могу найти это в gen-классе, и все примеры gen-class, которые я смог найти, используют поля класса только изнутри clojure; Я не уверен, как определить состояние: в gen-классе, так что он доступен из java, и я не знаю, как сделать их изменяемыми и общедоступными.

Следующим шагом будет попытка аннотации clojure, а затем использование поля fx: script вместо fx: controller для определения обратного вызова clojure ... но я хочу убедиться, что он выполним/не выполним с помощью deftype или gen -класс сначала.

Так может кто-нибудь сказать мне, можно ли сделать класс, доступный для Java, с общедоступными изменяемыми полями в clojure?

Спасибо.

ответ

3

Нет, вы не можете определить общедоступные изменяемые поля в Clojure. Это относится как к deftype, так и к gen-class.

Я полагаю, вы могли бы попытаться выяснить, будет ли JavaFX счастливым назвать геттер, и если да, то определите некоторые методы getFoo в Clojure.

+0

Спасибо, это чувство, которое я получаю. Мне пришло в голову, может быть, есть еще один способ заставить fxml поговорить с объектами Java через свойства, сеттеры, геттеры и т. Д., Но я пока не нашел этого. – Sonicsmooth

+0

Теперь вы можете просто добавить ту же @FXML-аннотацию (возможно, это было невозможно на момент написания) – Rick77

0

Довольно поздно в ответ, но если бы я нашел этот вопрос, другие люди могли бы так же ... :)

я наткнулся в той же самой проблеме OP (то есть, я пытаюсь дублируем в clojure пример FXML в учебнике javafx), и это мое решение:

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 (работает, я пробовал) или используя интроспекцию (не пробовал).

Надеюсь, что это поможет