A short guide on how to use NetBeans to create GUI and then use this GUI from clojure available

48 views
Skip to first unread message

prhlava

unread,
Feb 2, 2009, 1:42:34 PM2/2/09
to Clojure

Hello,

I have put a short guide on how to create Swing GUI using NetBenans
and how to get hands on this generated
GUI JForm (java class) from clojure.

I hope someone will find this useful...

http://www.dearm.co.uk/cgan/

or (.pdf version):

http://www.dearm.co.uk/cgan/cgan.pdf

Vlad

PS: Comments welcome...

hubritic

unread,
Feb 2, 2009, 2:05:10 PM2/2/09
to Clojure
Looks like I'll find it helpful. Thanks!

prhlava

unread,
Feb 2, 2009, 2:36:08 PM2/2/09
to Clojure

Cool, at least one positive response so far :-).

I have also put the .pdf file into this group's files section, called:

clojure-gui-and-netbeans.pdf


Vlad

AlamedaMike

unread,
Feb 2, 2009, 4:55:32 PM2/2/09
to Clojure
As it happens, I just downloaded NetBeans a few hours ago to start
working on this very issue. Thanks for saving me the trouble!

Also, Nokia has just changed the licensing of Qt Jambi so that LGPL
can be used. My sense is that Qt looks nicer than Swing, though I'd be
happy to hear if otherwise if not.

Timothy Pratley

unread,
Feb 2, 2009, 6:06:16 PM2/2/09
to Clojure
Hi Vlad,

A very useful guide.

> PS: Comments welcome...

Ok great, let me nitpick! :)

The java class you posted doesn't compile (unless name is renamed
person_name, and location renamed person_location).
The quote symbol rendered is not copy+paste friendly.
You can call main very easily: (MainFrame/main nil) however seeing the
default implementation does not return the created object, you can't
add the action listeners, so it isn't much use.
Here is another perspective on how you might code it (not better, just
different, but might prompt some ideas):
http://groups.google.com/group/clojure/web/app.clj

I found the guide very well written and easy to follow.


Regards,
Tim.

prhlava

unread,
Feb 3, 2009, 5:25:23 AM2/3/09
to Clojure

Hello Tim,

Thanks for pointing the mistakes in code and the quote thing. Will be
fixed in the next version of the guide...

> You can call main very easily: (MainFrame/main nil) however seeing the
> default implementation does not return the created object, you can't
> add the action listeners, so it isn't much use.

I thought of using it as the "start" function to make the GUI visible
(instead of .setVisible). Cheers for showing me how to call the
function.

> http://groups.google.com/group/clojure/web/app.clj

Options are good :-). Any objections on including your variant in the
guide?

> I found the guide very well written and easy to follow.

:-)

Vlad

prhlava

unread,
Feb 3, 2009, 6:31:24 AM2/3/09
to Clojure


> > You can call main very easily: (MainFrame/main nil) however seeing the
> > default implementation does not return the created object, you can't
> > add the action listeners, so it isn't much use.
>
> I thought of using it as the "start" function to make the GUI visible
> (instead of .setVisible). Cheers for showing me how to call the
> function.

It looks that the main is class method? It can be called as above but
I do not know if/how to call that after the MainFrame has being
created (i.e calling it on resulting object). In any case it does not
matter much (but I am still curious).

Vlad

Timothy Pratley

unread,
Feb 3, 2009, 6:13:14 PM2/3/09
to Clojure
Hi Vlad,


> Options are good :-). Any objections on including your variant in the
> guide?

Feel free to use it as you wish.


> It looks that the main is class method? It can be called as above but
> I do not know if/how to call that after the MainFrame has being
> created (i.e calling it on resulting object). In any case it does not
> matter much (but I am still curious).

Yes that's right, the "main" is generated as a static method. static
methods are invoked by their class, not object. So calling
MainFrame.main() runs the static method, but you cannot do m = new
MainFrame(); m.main();
The generated "main" creates a new instance of MainFrame and makes it
visible. There is no way for you to provide the object to "main" or
get the object from "main" without modifying the java code.


Regards,
Tim.


prhlava

unread,
Feb 4, 2009, 1:41:15 PM2/4/09
to Clojure

Hello Tim,

> Feel free to use it as you wish.

I have added the code (with attribution) to the guide.

Also, the .java generated code listing should now compile.

Updated guide is now on the same locations (including the files
section of this group).

>... So calling
> MainFrame.main() runs the static method, but you cannot do m = new
> MainFrame(); m.main();
> The generated "main" creates a new instance of MainFrame and makes it
> visible. There is no way for you to provide the object to "main" or
> get the object from "main" without modifying the java code.

Thank you for the explanation, now I get it...

Vlad

PS: Fixing the quote to be paste friendly is maybe possible somewhere
in LyX but so far I did not find out how...
Message has been deleted

AlamedaMike

unread,
Feb 4, 2009, 4:06:45 PM2/4/09
to Clojure
I'm having a problem that shows as:

java.lang.ClassNotFoundException: gui2.MainFrame
java.lang.ClassNotFoundException: gui2.MainFrame
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at clojure.lang.DynamicClassLoader.findClass
(DynamicClassLoader.java:52)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at clojure.import__776.doInvoke(boot.clj:1486)
at clojure.lang.RestFn.invoke(RestFn.java:413)
at user.eval__2296.invoke(Unknown Source)
at clojure.lang.Compiler.eval(Compiler.java:3891)
at clojure.lang.Repl.main(Repl.java:75)

I'm running Vista and when I enter the command "mklink /D . build
\classes\gui\" . (The order for link and target is reversed on
Windows.)
I get the message "Cannot create a file when that file already
exists."

It works fine when I substitute a name such as xyz for the
"."

I've tried everything I can think of, including copying the .class
files to the test-project directory. Nothing works.

I realize this isn't a Clojure issue as such, but I assume others
might
run into the same problem. Has anyone worked around this?

Michael Wood

unread,
Feb 4, 2009, 4:46:03 PM2/4/09
to clo...@googlegroups.com
Hi

On Wed, Feb 4, 2009 at 10:54 PM, AlamedaMike <limej...@yahoo.com> wrote:
>
> I'm having a problem that appears tied to this aspect of the guide
> (written for Linux):
>
>>> Before continuing, symlink build/classes/gui into the test-project directory (note, there is a "." as the last character in the 2nd command):
>
> cd ~/test-project
> ln -s build/classes/gui/ . // note the trailing period


>
> I'm running Vista and when I enter the command "mklink /D . build
> \classes\gui\"

> I get the message "Cannot create a file when that file already
> exists." It works fine when I substitute a name such as xyz for the
> "."
>

> I realize this isn't a Clojure issue as such, but I assume others will
> run into the same problem here. Has anyone worked around this?

Well, on Unix, the following:

$ ln -s /path/to/source .

is a short cut for:

$ ln -s /path/to/source source

I have never used Windows' mklink command, but perhaps this is what you want:

mklink /D gui build\classes\gui

--
Michael Wood <esio...@gmail.com>

Timothy Pratley

unread,
Feb 4, 2009, 5:57:39 PM2/4/09
to Clojure
> java.lang.ClassNotFoundException: gui2.MainFrame

To resolve gui2.MainFrame there needs to be MainFrame.class, in
directory gui2, in the current class-path.
Please check:
1) The directory name matches the namespace (If you can't get mklink
working, maybe just copy it instead?)
2) The current directory (parent of gui2) is in the class-path -cp
option when launching Clojure



AlamedaMike

unread,
Feb 4, 2009, 10:29:46 PM2/4/09
to Clojure
Michael, Timothy,

Thanks much to both of you.

>> 2) The current directory (parent of gui2) is in the class-path -cp
option when launching Clojure

The problem was that I had used the gui directory in the classpath,
rather than its parent. (The real problem is that I'm a Java noobie.)

The frame opens now and I can cancel it correctly. However, when I
click OK (using either the original app.clj or Timothy's version) I
get:

C:\Users\Mike\Documents\test-project>c:\clojure\clj.bat app.clj
Exception in thread "AWT-EventQueue-0" java.io.IOException: Stream
closed
at sun.nio.cs.StreamEncoder.ensureOpen(Unknown Source)
at sun.nio.cs.StreamEncoder.write(Unknown Source)
at sun.nio.cs.StreamEncoder.write(Unknown Source)
at java.io.OutputStreamWriter.write(Unknown Source)
at java.io.Writer.write(Unknown Source)
at clojure.lang.RT.print(RT.java:1186)
at clojure.pr__788.invoke(boot.clj:1516)
at clojure.lang.AFn.applyToHelper(AFn.java:184)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.apply__135.doInvoke(boot.clj:364)
at clojure.lang.RestFn.invoke(RestFn.java:428)
at clojure.prn__799.doInvoke(boot.clj:1540)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.apply__135.doInvoke(boot.clj:364)
at clojure.lang.RestFn.invoke(RestFn.java:428)
at clojure.println__805.doInvoke(boot.clj:1556)
at clojure.lang.RestFn.invoke(RestFn.java:413)
at clojure.eval__2299$fn__2301.invoke(app.clj:12)
at clojure.lang.Proxy__2305.actionPerformed(Unknown Source)
at javax.swing.AbstractButton.fireActionPerformed(Unknown
Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown
Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown
Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased
(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown
Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown
Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown
Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown
Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown
Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown
Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

The problem is in the println function, as it works fine when I
comment them out. I assume this is some sort of problem sending text
to the DOS/Vista command shell that doesn't happen under *nix. Also,
no text appears in the command shell when I enter some into the boxes
and click OK.

This isn't critical to running the app, of course, though having print
capability back to the command shell makes an excellent debugging
tool. It seems clear it will be an issue for anyone on Windows, and
for a broad range of apps. As this is well beyond my modest Java
powers, any ideas would be appreciated.

Thanks again for you help.

AlamedaMike

unread,
Feb 4, 2009, 10:33:09 PM2/4/09
to Clojure
>> The quote symbol rendered is not copy+paste friendly.

The quote problem can be fixed by using:

(import (quote (gui2 MainFrame))) etc...

instead of using the single quote mark.

Timothy Pratley

unread,
Feb 4, 2009, 11:46:06 PM2/4/09
to Clojure

> C:\Users\Mike\Documents\test-project>c:\clojure\clj.bat app.clj
> Exception in thread "AWT-EventQueue-0" java.io.IOException: Stream
> closed

The reason you are seeing this is that stdout has closed when the main
clj program reaches the end, but the Swing thread is still running. I
remember having this problem with an older build of Clojure but it
doesn't happen for me anymore, so either something changed or the .bat
file launching the script affects this behavior (I'm running on XP).

If you put (read) at the end of your .clj file it will keep stdout
open (until you enter some text at the consol).

Here is a version which avoids the issue altogether by using a Dialog
instead of stdout:
http://groups.google.com/group/clojure/web/app.clj


Regards,
Tim.

prhlava

unread,
Feb 5, 2009, 10:04:00 AM2/5/09
to Clojure
> 2) The current directory (parent of gui2) is in the class-path -cp
> option when launching Clojure

Updated the guide with note about CLASSPATH - basicaly, I have current
directory (".") listed in it.

Also, replaced quote character with "quote" word in the code.

Updated version so far only here:

http://clojure.googlegroups.com/web/clojure-gui-and-netbeans.pdf

Vlad

AlamedaMike

unread,
Feb 5, 2009, 10:24:53 PM2/5/09
to Clojure
Vlad, thanks for updating the guide. I've saved the new version.

Tim, thanks for the ideas. I've tried both and both work well.

It did get me thinking that it would be great to have a way to
interrogate an open gui app from the command line, or perhaps, from a
separate area in the app itself (say, a special "debugging" tab in the
main window). Having a standard way to alter the app while it's
running would be some kind of wonderful. If anyone has any ideas on
that I'd love to hear them.

Thanks again for your help guys.

Timothy Pratley

unread,
Feb 5, 2009, 11:11:34 PM2/5/09
to Clojure
> It did get me thinking that it would be great to have a way to
> interrogate an open gui app from the command line, or perhaps, from a
> separate area in the app itself (say, a special "debugging" tab in the
> main window). Having a standard way to alter the app while it's
> running would be some kind of wonderful. If anyone has any ideas on
> that I'd love to hear them.

Indeed you can do all those things using a REPL.You can interactively
do pretty much anything. You could even embed a REPL into your
application with a socket back-door, connect to it and really have fun
with your users.

Here is a semi-practical example (copy these into your REPL one at a
time):

(defn add-button
"Create a JButton and add it to a Container with an ActionListener"
[#^java.awt.Container container, #^String button-label, function]
(.add container (doto (javax.swing.JButton. button-label)
(.addActionListener
(proxy [java.awt.event.ActionListener] []
(actionPerformed [evt] (function evt)))))))

(defn later [function]
(java.awt.EventQueue/invokeLater function))
(def frame (javax.swing.JFrame. "inter-app"))
(later #(.setVisible frame true))
(later #(add-button frame "greeter" (fn [evt] (println "hello" evt))))
(later #(.pack frame))
(later #(.dispose frame))


Regards,
Tim.

Emeka

unread,
Feb 6, 2009, 6:36:53 AM2/6/09
to clo...@googlegroups.com
Tim

You could even embed a REPL into your

application with a socket back-door, connect to it and really have fun
with your users.
I am interested, could you make a rough patch for me to draw some inspiration from

Emeka


Timothy Pratley

unread,
Feb 11, 2009, 4:39:37 AM2/11/09
to Clojure


On Feb 6, 10:36 pm, Emeka <emekami...@gmail.com> wrote:
> You could even embed a REPL into your
> application with a socket
> I am interested, could you make a rough patch for me to draw some
> inspiration from

There is a handy server_socket.clj in clojure-contrib which makes it
relatively trivial to set up:
http://groups.google.com/group/clojure/web/srepl.clj
[you need to have checked out clojure.contrib and have it in your
start script]
Once it is running, telnet to localhost 8888 and paste in this:
(srepl/later #(.setVisible srepl/frame true))
(srepl/later #(srepl/add-button srepl/frame "second"
(fn [evt] (println "second hello" evt))))
(srepl/later #(.pack srepl/frame))
And it adds a second button to the GUI on the fly.


Regards,
Tim

AlamedaMike

unread,
Feb 11, 2009, 5:30:18 AM2/11/09
to Clojure
Tim,

Thanks much. Very useful and surprisingly simple.

Mike
Reply all
Reply to author
Forward
0 new messages