Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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-lineis 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 :)

like image 510
Isaac Avatar asked Jul 29 '10 21:07

Isaac


2 Answers

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...)

like image 68
Bill K Avatar answered Oct 05 '22 23:10

Bill K


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.

like image 22
Tom Hawtin - tackline Avatar answered Oct 06 '22 00:10

Tom Hawtin - tackline