简体   繁体   English

使用Swing时的竞争条件(?)

[英]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. 我已经尝试使用OpenGL到Penumbra尝试使用Graphics上下文直接在JPanel上绘图。

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. 这将是很好的,除了我遇到了一些麻烦...我编译我的代码,并且〜25次中的〜1次,图形(这是示例的矩形)绘制得很好。 The other ~24 times, it doesn't. 其他~24次,它没有。

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: 功能draw-line如下:

(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. 我也重置了lein和slime / swank和emacs。 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. 确保您始终在EDT。 If you see your GUI acting randomly that is generally the cause. 如果你看到你的GUI随机起作用通常是原因。 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). 您可以尝试,只是为了看到,找到任何与swing组件交互并让它打印出Thread.getCurrentThread()。toString()(或非常接近的东西)的方法。

It should always print out a thread name and you'll see the letters AWT embedded in there somewhere. 它应该总是打印出一个线程名称,你会在那里看到嵌入字母的AWT。 You could even store off that thread, test against it on every call into Swing and assert if it's not the same. 您甚至可以存储该线程,在每次调用Swing时对其进行测试,并断言它是否不相同。

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...) 实际上我不知道为什么Sun从来没有构建一个JDK的“调试”版本,当这样的事情发生时会断言(就像从一个非awt线程中调用一些swing线程一样......)

You should be overriding paintComponent in the panel. 您应该覆盖面板中的paintComponent (Choice of JPanel probably isn't the best - use JComponent and certain set-opaque on it.) (选择JPanel可能不是最好的 - 使用JComponent和某些set-opaque就可以了。)

Also, I guess you should be on the AWT EDT. 另外,我猜你应该参加AWT EDT。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM