Monday, December 20, 2010

First stab at creating a Clojure/Java launcher with Swing

One pain I hate about java is that I have to tell the JVM my classpath (and clojure path) in order to run my program.  Unlike python, where I can do an import wherever I want, and I can even dynamically add a path for the python interpreter to search for modules, there's no such thing for Java.  Basically you tell java where all the jars, .class files and .clj files are when you first launch the JVM, or it won't be able to find them.

Because of this pain in the butt, I want to create a Swing app where the user can select any external jars, .class files, paths to .class files, or .clj files so that launching an app will be easier.  I may even add some options for special JVM args to pass in.  And if I get REALLY fancy, maybe I'll even add a text area for my own repl and use either clojure.contrib.shell or clojure.contrib.server-socket.  If I don't do this, then I'll need to launch a subprocess with a new terminal.


I actually just discovered that clojure has some special miglayout support, as I was going to use this layout manager for my GUI, since that seems to be the most "hand-coded friendly".  However, I already implemented a little code already, mostly due to reading some of Stuart Sierra's blog on writing Swing apps with clojure.

But here's a first stab at this.  Remember when you launch clojure, that you'll need to include the miglayout jar in your classpath.  By the way, one thing I have not liked about ANY of the books I have read on clojure is in explaining the synatx for importing (use, require, or import) libraries.  Sometimes you have to quote a list, sometimes you don't, and no one gives any good explanation on when they are required.

(ns sojourner.gui
  (:import (javax.swing JPanel JButton JLabel JFrame JTextField)
               (net.miginfocom.swing MigLayout)))


(defn make-launcher []
  (let [ ext-jar-lbl (JLabel. "External Jars")
          ext-jar-field (JTextField. "Add paths here")
          panel (doto (JPanel. (MigLayout.))
                      (.add ext-jar-lbl)
                      (.add ext-jar-field "wrap") ) ]
        ; return the frame after we're done here
        (doto (JFrame. "Java Launcher")
          (.setContentPane panel)
          (.setSize 300 150)
          (.setVisible true))))

(def frame (make-launcher))


I tested this out in my repl by using the load function (I named this file gui.clj, and don't forget to add this to your classpath). This is pretty cool, as you can then use the (use :reload 'gui) function to make changes to the code above.


Right now, all it shows is a frame with a label and a JTextField.  It isn't even listening to any events yet, but it's a start.

No comments:

Post a Comment