Featured Post

Return of the prodigal son

I'm a man and as a man I sin. My eval doings have come back to me making me miserable and little man. I spent those two months on meditation and repentance. I swore to my self that I'll relinquish of all eval and I'll walk on the path of truth.

Read More

Clojure JavaFx 2.0 simple app

Posted by Emil Kruczek | Posted in Coding | Posted on 08-06-2011

0

Hello. In my previous post I’ve shown how to make clojure, leiningen and JavaFx 2.0 Beta work together. Today I’ll show you my simple JavaFx application.

First of all I think that UI of application should be written declaratively. It’s fun, fast and maybe it’s some habit of mine from writing WPF applications in XAML. So to make things simpler for me, I’ve came with one simple macro and two utility functions.

(ns pl.altasoft.fx)

(defn make-param
  "Transform keyword into setter function"
  [param-name]
        (let [[f & rest] (name param-name)]
             (symbol (apply str (list* ".set" (Character/toUpperCase f) rest)))))

(defn organize-args
  "Takes seqence of arguments and divides them into params and argumetnts required for constructor. Returns [{params} [req]]"
  [& args]
     (loop [[key & rest] args arguments args  params {} req []]
        (if (seq arguments)
            (if (keyword? key)
                 (recur (next rest) (next rest) (conj params {key (first rest)}) [])
                   (if (seq rest)
                       [params (vec (conj rest key))]
                       [params [key]]))
                [params req])))

(defmacro fx
  "Creates forms which makes new object of class class and forms that make operations on this object. ex: (import javafx.scene.text.Text) (eval (fx javafx.scene.layout.BorderPane :left (fx Text "Hello World")))"

  [class & args]
          `(let [[params# req#] (organize-args ~@args)]
                  `(doto (new ~~class ~@req#)
                         ~@(when (seq params#)
                              (for [param# params#]
                                `(~(make-param (key param#)) ~(val param#)))))))

Now we need two generated classes. One is loaded by JavaFx application “launcher” and and second is launched by the first one :) . Pretty complicated but hang on.

(ns pl.altasoft.core
  (:gen-class))

(defn -main [& args]
  (javafx.application.Application/launch pl.altasoft.simpleapp (into-array String [])))

And the second class containing code of our JavaFx application

(ns pl.altasoft.simpleapp
  (:gen-class
   :extends javafx.application.Application)
  (:import (javafx.stage Stage)
           (javafx.scene Scene)
           (javafx.scene.text Text)
           (javafx.scene.layout BorderPane))
  (:use [pl.altasoft.fx]))

(defn -start
         [app stage]
         (eval
           (fx Stage :visible true :width 300 :height 200 :title "hello world"
               :scene (fx Scene
                        (fx BorderPane :left (fx Text "hello")
                            :right (fx Text "Right")
                            :top (fx Text "top")
                            :bottom (fx Text "Bottom")
                            :center (fx Text "In the middle!"))))))

The project.clj is the same as in previous post

And here it is our simple app.

Simple JavaFx application

And here are sources of my simpleapp example
simpleapp project

Comments are closed.