我正在将 Swing 和 Java3D 结合在一起。 swing 组件的操作应该使用事件分配器线程完成,而 Java3D 组件的操作应该在 BehaviourSchedulerThread 中完成。
Java3D 渲染场景,然后执行与场景关联的所有行为。
我在 Canvas3D 上启用了 MouseListener。事件被发布到 AWT 事件队列中。然后我想根据这些事件修改 Java3D 环境,所以我使用了一个特殊的行为,我可以在其中发布 Runnable 的。这确保了 Runnable 在 Java3D 的行为周期中执行(并且在渲染周期中不修改任何内容)。
假设Behavior中的一些操作想要修改Swing模型。然后我必须向 EDT 发布一个新的 Runnable。
这是正确的做法吗?
使用这种技术,我在鼠标监听器上遇到了很多问题。我在行为中更新了 Java3D 模型中的一个点,同时更新了 swing GUI。
更新: 问题可以更明确地定义如下:
我有一个 JButton“旋转立方体”,它有一个 ActionListener。一旦触发了 ActionListener,它就会将 AWTEvent 推送到 Java3D 行为中。 Behavior 触发后,它会修改 Scene 图,然后修改 JButton actionListener 和文本以变为“停止旋转”。
- 点击 JButton 两次。
- 第一个 AWTEvent 被分派(dispatch)到 SpinActionListener。立方体开始旋转,JButton actionListener 被修改为
StopSpinningActionListener
。 - 第二个 AWTEvent 被分派(dispatch)到 StopSpinningActionListener。立方体停止旋转,JButton actionListener 修改为
SpinActionListener
。
实际情况如下:
- 点击 JButton 两次。两个
AWTEvent
都被分派(dispatch)到SpinActionListener
。这将创建一个 Runnable 以在 J3D 行为内部执行。 - 第一个 AWTEvent 启动一个计时器来旋转立方体。然后它向 EDT 发送一个 Runnable 来修改按钮。
- 第二个 AWTEvent 启动一个计时器来旋转立方体。立方体现在将以两倍的速度旋转。然后它向 EDT 发送一个 Runnable 来修改按钮。
显然,我不应该依赖于 AWTEvent 的顺序处理。我不能在 EDT 中等待行为触发,因为任何 SwingUtilities.invokeAndWait() 都会导致死锁。
最佳答案
哪个 WakeupCriterion
用于唤醒您的特殊 Behavior 对象?
Java 3D 的源代码包括实用程序类
com.sun.j3d.utils.behaviors.mouse.MouseBehavior/MouseRotate
它监听 Canvas3D 的 AWTEvents
。可以选择两个备选方案之一:
MouseListener
和WakeupOnBehaviorPost
或WakeupOnAWTEvent
。
此代码示例可能会有所帮助。
通过 SwingUtilities.invokeLater
从 Behavior.processStimulus
方法中启动 Swing 组件更新应该不会导致任何问题。
关于java - 结合 Java Swing 和 Java3D : performance problems with concurrency,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8847812/