Race condition (?) when using Swing
I've moved on from trying to use OpenGL through Penumbra to trying to draw directly on a JPanel using its Graphics context.
This would be great, except I'm running into some trouble… I compile my code, and ~1 time out of 25, the graphic (it's a rectangle for the example) draws just fine. The other ~24 times, it doesn't.
Here's my code:
(def main
(let [frame (JFrame. "This is a test.")
main-panel (JPanel. (GridBagLayout.))
tpan (proxy [JPanel] [] (getPreferredSize [] (Dimension. 600 400)))]
(doto frame
(set-content-pane
开发者_如何学编程 (doto main-panel
(grid-bag-layout
:gridx 0 :gridy 0
tpan
:gridx 0 :gridy 1
xy-label)))
(pack-frame)
(set-visible))
(draw-line tpan Color/RED 250 250 50 50)))
The function draw-line
is below:
(defn draw-line [panel color x y w h]
(let [graphics (.getGraphics panel)]
(doto graphics
(.setColor color)
(.drawRect x y w h))))
I have no idea what is going on. At first I thought it was the refs I was working on, but then I took those out, and still have these problems. I've reset lein and slime/swank and emacs, too. I'm quite puzzled.
As usual, any help would be appreciated. I hope this is a question with an answer! Lately, I seem to be asking the impossible :)
Ensure that you are always on the EDT. If you see your GUI acting randomly that is generally the cause. Race conditions are critical to swing because it's designed to be entirely single-threaded.
What you might try, just to see, is find any method that interacts with a swing component and have it print out the Thread.getCurrentThread().toString() (or something very close to that).
It should always print out a thread name and you'll see the letters AWT embedded in there somewhere. You could even store off that thread, test against it on every call into Swing and assert if it's not the same.
Actually I don't know why Sun never built a "Debug" version of the JDK that would assert when things like this happened (like when some swing thread was called from a non-awt thread...)
You should be overriding paintComponent
in the panel. (Choice of JPanel
probably isn't the best - use JComponent
and certain set-opaque
on it.)
Also, I guess you should be on the AWT EDT.
精彩评论