Referring to this SO question on a first UI program in Clojure, I created a new Leiningen
app project:
lein new app a-ui-app
copied the source into the core.clj
that leiningen generated and modified the -main
routine to call it
(defn -main
"See https://stackoverflow.com/questions/2792451/improving-my-first-clojure-program?rq=1."
[& args]
;; work around dangerous default behaviour in Clojure
(alter-var-root #'*read-eval* (constantly false))
(doto panel
(.setFocusable true)
(.addKeyListener panel))
(doto frame
(.add panel)
(.pack)
(.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
(.setVisible true))
(loop []
(draw-rectangle panel @x @y)
(Thread/sleep 10)
(recur))
)
I then run it via either
lein run
or
lein uberjar
java -jar ./target/a-ui-app-0.1.0-SNAPSHOT-standalone.jar
In both cases, the app works well, but in the terminal that I used to start it up, I get an exception after a random delay of several seconds:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: No matching clause: 157 at a_ui_app.core$fn__16$fn__21$fn__22.invoke(core.clj:19) at clojure.lang.AFn.call(AFn.java:18) at clojure.lang.LockingTransaction.run(LockingTransaction.java:263) at clojure.lang.LockingTransaction.runInTransaction(LockingTransaction.java:231) at a_ui_app.core$fn__16$fn__21.invoke(core.clj:17) at a_ui_app.core.proxy$javax.swing.JPanel$KeyListener$6c415903.keyPressed(Unknown Source) at java.awt.Component.processKeyEvent(Component.java:6340) at javax.swing.JComponent.processKeyEvent(JComponent.java:2809) at a_ui_app.core.proxy$javax.swing.JPanel$KeyListener$6c415903.processKeyEvent(Unknown Source) at java.awt.Component.processEvent(Component.java:6159) at java.awt.Container.processEvent(Container.java:2083) many more lines...
I made no changes to project.clj
-- just used the leiningen-generated one.
I'd like to understand what's going on. I am by no means knowledgeable in Java Threading. Is the problem related to the way leiningen launches the app's Java threads? Is it unavoidable? If not, how can I fix it, both for this little sample program and going forward, as a project pattern for future projects using the UI thread (which I think is AWT-EventQueue-0
).