2013-05-19 2 views
1

Следуя учебному курсу JavaFX здесь: http://docs.oracle.com/javafx/2/get_started/fxml_tutorial.htm, пытаясь заставить его работать в Clojure. На данный момент я просто делаю lein run после настройки :aot :all и прочего с (:gen-class) и т. Д. Потребовалось несколько дней, но теперь, похоже, в основном работает.Clojure и JavaFX 2.0 - Как получить идентификатор элемента из функции обратного вызова clojure

В src/jfxtwo/ClojureExampleController.clj:

(defn -handleSubmitButtonAction [^ActionEvent event] 
    (let [actiontarget (Text.)] 
    (println "event button pressed") 
    (println "Event instance:" event) 
    (println "Event class:" (class event)) 
    (.setText actiontarget "Sign in button pressed..."))) 

В resources/fxml_example.fxml:

<GridPane fx:controller= "jfxtwo.ClojureExampleController" 
     xmlns:fx= "http://javafx.com/fxml" 
     alignment= "center" hgap= "10" vgap= "10" 
     styleClass= "root" > 
... 
    <Button text= "Sign In" 
    onAction= "#handleSubmitButtonAction" /> 

... 
    <Text fx:id= "actiontarget" 
     GridPane.columnIndex= "1" GridPane.rowIndex= "6" /> 
... 

У меня есть код Clojure в состоянии прочитать FXML и CSS файл для создания правильного графического интерфейса. Когда я нажимаю кнопку, я могу видеть обработчик события, но я не знаю, как получить доступ к Text, который я хочу изменить, или экземпляр ActionEvent, связанный с нажатием кнопки. Я попытался (println event) и (println (class event)) ожидал увидеть что-то о ActionEvent, например, но это только приводит показывая мне, что по какой-то причине функция обратного вызова считает, что событие является ClojureExampleController, хотя тип намек говорит, что это должно быть ActionEvent:

event button pressed 
Event instance: #<ClojureExampleController [email protected]> 
Event class: jfxtwo.ClojureExampleController 

Java-код, чтобы сделать это выглядит следующим образом:

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

Clearle @FXML аннотаций делает волшебство здесь. Что происходит, и как я могу сделать эту работу в Clojure?

Кроме того, существует ли способ привязки кнопки к изменению текста непосредственно в FXML, поэтому мне не нужно обрабатывать изменение gui> gui в коде, а вместо этого обрабатывать только логика, связанная с нажатием кнопки? Я предполагаю, что да, но я не дошел до этого в учебнике.

спасибо!

ответ

1

Вам нужен явный this аргумент в обработчике:

(defn -handleSubmitButtonAction [this ^ActionEvent event] 
    ...) 

Возможно, более точный способ сдачи этого является то, что eventявляетсяthis аргумент в обработчике, как экспонируются в тексте вопроса, и вы должны добавить второй аргумент, чтобы принять событие и переместить к нему подсказку типа (и, вероятно, переименовать первый аргумент в this для удобства чтения).

С учетом того, что ваш код вообще вызван, кажется, что JavaFX рад вызывать обработчик, не передавая его вообще, если ему это неинтересно (о чем свидетельствует отсутствие формального параметра соответствующий ему).

Цель единственного типа заключается в том, чтобы позволить компилятору Clojure избегать испускания отражающего кода при вызове методов ActionEvent на event. Это не предотвратит передачу объекта другого типа в функцию.

+0

Интересно, почти (?) Работал. Я получаю это, когда я нажимаю кнопку: 'Caused by: clojure.lang.ArityException: Неверное количество аргументов (1) передано в: ClojureExampleController $ -handleSubmitButtonAction'. Я также попытался использовать '& args' в качестве аргумента и напечатал' (count args) ', и он просто вернул 1. Итак, как-то clojure думает, что он получает один аргумент. – Sonicsmooth

+0

Это означает, что он получает один аргумент. Вам нужно будет убедить JavaFX пройти в другом. Или вы можете посмотреть, что из раздела «Использовать скриптовый язык для обработки событий» предлагает учебник и просто подключить функцию Clojure в качестве обработчика. (Обратите внимание, что в учебнике упоминается Clojure в этом разделе как один из языков, который можно использовать таким образом.) –

+0

Еще одна вещь: Clojure поддерживает аннотации в 'definterface' (на самом интерфейсе),' deftype' и 'defrecord' (на созданные типы и их поля и методы) и 'gen-class' (на самом классе, его конструкторах и методах). См. Https://gist.github.com/richhickey/377213 для примеров (в Gist нет примеров 'gen-class', поскольку поддержка аннотаций в gen-class была недоступна, она работает в значительной степени в том же Кстати, вы добавляете аннотации в виде метаданных по соответствующему имени, NB. Это будет имя в спецификации gen-class, а не 'defn'. –

Смежные вопросы