Clojure, JavaFX Eventhandler not in namespace - javafx

i'm trying to make a EventHandler for my FXML based View in my Clojure Projekt.
As described here: http://drowsy.de/blog/?p=7 i added in the FXML this
onAction="(use 'ui.listener) (add-tolist-listener event)"
to a button.
But when i launch the application i get following error message:
LoadException Error resolving onAction='(use 'ui.listener)
(add-tolist-listener event)', either the event handler is not in
the Namespace or there is an error in the script.
In ui.listener is the eventhandler
(defn add-tolist-listener [event]
(println "I'm a Button"))
Any idea why this doesn't work?
I tried it with this notation
onAction = #add-tolist-listener
and it didn't worked too.
Thanks!

I am completely unfamiliar with JavaFX, however:
onAction="(use 'ui.listener) (add-tolist-listener event)"
This looks like Java code, so having Clojure syntax in here doesn't seem like it would work? I suspect you would have to call your Clojure code using Java?
Going off "Calling Clojure code from Java".
You would have to try something like:
ui.listener.add_tolist_listener
You might also find this blog post gives you another idea to try: Invoking Clojure code from Java.

Now is set up the action in my start function via
(.setOnAction (.lookup root "#startCalculationBtn")
(proxy [EventHandler] []
(handle [^ActionEvent event]
(start-calculation))
)
)
And it works.

Related

What does Gluon SceneBuilder look for in JAR files?

Using Clojure, I'm trying to write a custom JavaFX component for use in Gluon SceneBuilder, to be loaded up from a .jar file. That is, I'd like to point SceneBuilder to the .jar with my custom class, and have the thing show up in the list of draggable items on the left.
I can make the visual structure show up with FXML only, but I'd like to include some behavior as well.
After doing the (:gen-class) stuff in my Clojure source, running lein uberjar, and using the fx:root construct in the FXML, I'm able to use the resulting class in a modified version of the official Java example.
When I instantiate my custom class in the CustomControlExample, I see evidence of the Clojure init code running (via printlns and other stuff in the graphics).
So my custom class appears to work normally. It has two constructors -- with and without a String argument, and extends from HBox. I can verify these when I view the resulting .class file in NetBeans and also using JarExplorer. The class has a ton more stuff in it, due to being a Clojure constructed class, but it has at least the same number and type of constructors as the example.
The problem is my custom component does not appear in the SceneBuilder when I import the uberjar file.
So the question is: What exactly does SceneBuilder need to see in the class to make it appear as a custom draggable component?
Here is the relevant portion of my one source file (it includes a utility library for dealing with starting up the FX runtime).
src/toyui/GridSettingsPane.clj:
(ns toyui.GridSettingsPane
(:gen-class
:extends javafx.scene.layout.HBox
:post-init post-init
:init init
:constructors {[] []
[String] []})
(:use [jfxutils.core :exclude [-main]]))
(defn -init
([]
(-init "unnamed-init"))
([name]
(println "hi from -init")
[[] []]))
(defn -post-init
([this]
(-post-init this "unnamed-post-init"))
([this name]
(println "hi from -post-init")
(jfxutils.core/app-init)
(let [loader (javafx.fxml.FXMLLoader. (clojure.java.io/resource "GridSettingsPane.fxml"))]
(.setRoot loader this)
(.setController loader this)
(.load loader)
loader))))
I discovered that SceneBuilder was using some real-time class loading. Clojure defaults to *use-context-classloader* = true, so I was able to get the class to load, sort of, by modifying the scenebuilder code a little as in my comment above. However it still was having some trouble with finding some type of resource. I figured it was still probably due to class paths and the like.
In the process I also discovered that the SceneBuilder dynamically creates a little FXML file (stream, actually), which says, among other things, <?import toyui.GridSettingsPane?>, and the runs the regular FXML loader on that stream.
So I went and modified FXMLExample to import my Clojure class from within the .fxml file and it worked.
So the conclusion is yes, my class will work as-is in the FXML when running from a regular program, but for some reason doesn't load up when the jar explorer is looking.

Creating a JavaFX proxy causes a UnsupportedOperationException

I'm trying to write a JavaFX app in Clojure. As a simple test, I wanted to try to just launch a Hello World. To extend Application, I decided to try using proxy instead of :gen-class. I wanted to be able to create a bare-bones function that creates an Application, instead of requiring me to write the boilerplate every time.
The simple example I came up with was:
(let [^Application app
(proxy [Application] []
(start [self stage] (println "Hello World")))]
(Application/launch ^Class (.getClass app)
(into-array String [])))
The problem is, this causes an UnsupportedOperationException:
UnsupportedOperationException start chat.graphics_tests.javafx_wrapper.proxy$javafx.application.Application$ff19274a.start (:-1)
It seems like it can't find the start method that I implemented. My first thought was that the arguments to start were wrong. They seem correct though. The first argument it receives is "this", then the primary stage. I tried different numbers of arguments though, and I still get the same error. According to the docs:
If a method fn is not provided for an interface method, an
UnsupportedOperationException will be thrown should it be
called.
Which further my this suspicion.
The errors quite vague. Does anyone see what the problem is?
When writing proxy class definitions in Clojure you do not need the explicit self parameter in the method signature. The current instance will be implicitly bound to this which you will be able to use inside the methods.
Therefore your proxy call should look like this:
(proxy [Application] []
(start [stage] (println "Hello World")))
This appears to be because Application/launch requires a named class, which proxy doesn't create. (see the comment at the bottom of the answer. I'm trusting #Sam here).
I ended up caving and using :gen-class, and got it working after some fiddling.

How to implement early stopping as an extension

As this thread, we can stop iteration loop by setting function (f:trainer -> bool) as Trainer's stop_triger.
But in this way, I think we can't use other extension such as LogReport which use stop_trigger=((args.epoch, '10')).
So, my question is how to implement early stopping as the Extension and how to send a signal to stop trainer's iteration from Extension.
thanks.
I implemented the example code on gist,
and updated the answer on the original thread.
I noticed that stop_trigger originally uses tuple notation like (args.epoch, '10'), instead we need to change to pass a callable object (EarlyStoppingTrigger in above example).

Meteor.autorun vs Tracker.autorun?

What is the difference between Meteor.autorun and Tracker.autorun?
are they just aliases?
is one deprecated?
is there any instance where one is preferable to the other?
I'm well aware of the difference in using this.autorun in template lifecycle callbacks, but have seen these two used interchangeably and just want to be sure I haven't missed a trick.
Well, it can easily be found out with the identity operator.
This will be false because it is not the same function:
(function() {} === function() {})
Let's try with the two autorun :
(Meteor.autorun === Tracker.autorun)
This returns true. So yes it's only a pure alias.
However, only Tracker.autorun is documented. I suspect some kind of old API left for compatibility...
Let's check some Meteor code on GitHub!
File : deprecated.js
Meteor.autorun = Tracker.autorun;
This is in deprecated.js, it says some things about //Deprecated functions and some backward compatibility with Meteor 0.5.4. It seems pretty clear which one you should use.
You can find some other old timers in there, such as Deps...
Try to run Meteor.autorun(); in the console, it throws the following error Uncaught Error: Tracker.autorun requires a function argument like you were trying to run Tracker.autorun();

How do I return an Array from grails / jdo to Flex

this seems really simple but I haven't gotten this to work. I am building my app with grails on google app engine. This pretty much requires you to use JDO.
I am making an HTTP call from flex to my app. The action that I am calling on the grails end looks like so
def returnShowsByDate = {
def query = persistenceManager.newQuery( Show )
def showInstanceList = query.execute()
return (List<Show>) showInstanceList
}
I have tried just returning "hello from grails" and that works just fine. I have alos tried the following
return showInstanceList
the JDO docs say the query.execute() returns a collection. Why I cant just return that to Flex I have no clue.
Any thoughts?
after playing around with this some more I was able to get a result event back by have grails convert the object to JSON or XML
wish I could just return a damn ArrayList. That Would be better but oh well.
OK so I found the fundamental problem and I am answering my own question.
I noticed that I got a fault event when using the JSON stuff too, so I launched a browser and went to the list view that grails provided. Then I requested data from Flex and it worked.
Long story short persistenceManager was null if I didn't go to the html view first so in my method that is being called from Flex I added the following.
if(!persistenceManager)
def persistenceManager
all works well now.

Resources