我正在将Swing和Java3D结合起来使用。对于swing组件的操作应该在事件分发线程中进行,而对于Java3D组件的操作则应该在行为调度器线程中进行。
Java3D渲染场景并执行与场景相关的所有行为。
我在Canvas3D上启用了MouseListener,并将事件发布到AWT事件队列中。然后,我想根据这些事件修改Java3D环境,因此我使用了一个特殊的Behavior,在其中可以发布Runnable,这确保了这些Runnable在Java3D的行为周期内执行(而不是在渲染周期中修改任何内容)。
假设某些行为中的操作要修改Swing模型,则必须向EDT发布一个新的Runnable。
这是否是正确的方法?
使用这种技术,在鼠标监听器上我遇到了许多问题。我在行为中更新Java3D模型中的一个点,并同时更新swing GUI。
更新:
问题可以更清楚地定义如下:
我有一个名为“spin cube”的JButton,它具有ActionListener。一旦ActionListener触发,它就会将AWTEvent推送到Java3D Behavior中。一旦Behavior触发,它就会修改场景图,然后修改JButton ActionListener 和文本变成“停止旋转”。
- 点击JButton两次。
- 第一个AWTEvent被分派到SpinActionListener。立方体开始旋转,并将JButton ActionListener 修改为
StopSpinningActionListener
。 - 第二个AWT事件被分派到StopSpinningActionListener。立方体停止旋转,并将JButton ActionListener 修改为
SpinActionListener
。
实际发生的事情是:
- 点击JButton两次。两个
AWTEvent
都被分派到SpinActionListener
。这创建了一个要在J3D Behavior中执行的Runnable。 - 第一个AWTEvent启动了一个定时器来旋转立方体。然后它发布一个Runnable到EDT以修改按钮。
- 第二个AWTEvent启动一个计时器来旋转立方体。现在,立方体将以两倍的速度旋转。然后,它会向EDT发布一个Runnable来修改按钮。
显然,我不应该依赖于AWTEvent按顺序处理。我不能在EDT中等待行为触发,因为任何SwingUtilities.invokeAndWait()都会导致死锁。