使用 Swing 时的竞争条件 (?)
我已经从尝试通过 Penumbra 使用 OpenGL 转向尝试使用 JPanel 的 Graphics 上下文直接在 JPanel 上绘图。
这太好了,除非我遇到了一些麻烦……我编译了我的代码,大约 25 次中有 1 次,图形(在示例中是一个矩形)绘制得很好。其他~24次,没有。
这是我的代码:
(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)))
函数draw-line
如下:
(defn draw-line [panel color x y w h]
(let [graphics (.getGraphics panel)]
(doto graphics
(.setColor color)
(.drawRect x y w h))))
我不知道发生了什么。起初我以为是我正在处理的裁判,但后来我把它们拿出来,仍然有这些问题。我也重置了 lein 和 slime/swank 和 emacs。我很纳闷。
像往常一样,任何帮助将不胜感激。我希望这是一个有答案的问题!最近,我似乎在问不可能的事:)
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 :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
确保您始终处于 EDT。如果您发现 GUI 随机运行,这通常就是原因所在。竞争条件对于 swing 至关重要,因为它被设计为完全单线程。
您可能会尝试,只是为了看看,找到与 swing 组件交互的任何方法,并让它打印出 Thread.getCurrentThread().toString() (或非常接近的东西)。
它应该始终打印出线程名称,并且您会在某处看到嵌入的字母 AWT。您甚至可以存储该线程,在每次调用 Swing 时对其进行测试,并断言它是否不相同。
实际上,我不知道为什么 Sun 从未构建过 JDK 的“调试”版本,该版本会在发生此类情况时进行断言(例如,当从非 awt 线程调用某个 swing 线程时......)
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...)
您应该覆盖面板中的
paintComponent
。 (选择JPanel
可能不是最好的 - 使用JComponent
和某些set-opaque
。)另外,我想你应该是在 AWT EDT 上。
You should be overriding
paintComponent
in the panel. (Choice ofJPanel
probably isn't the best - useJComponent
and certainset-opaque
on it.)Also, I guess you should be on the AWT EDT.