结合Java Swing和Java3D:并发性能问题

11

我正在将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 和文本变成“停止旋转”。

  1. 点击JButton两次。
  2. 第一个AWTEvent被分派到SpinActionListener。立方体开始旋转,并将JButton ActionListener 修改为StopSpinningActionListener
  3. 第二个AWT事件被分派到StopSpinningActionListener。立方体停止旋转,并将JButton ActionListener 修改为SpinActionListener

实际发生的事情是:

  1. 点击JButton两次。两个AWTEvent都被分派到SpinActionListener。这创建了一个要在J3D Behavior中执行的Runnable。
  2. 第一个AWTEvent启动了一个定时器来旋转立方体。然后它发布一个Runnable到EDT以修改按钮。
  3. 第二个AWTEvent启动一个计时器来旋转立方体。现在,立方体将以两倍的速度旋转。然后,它会向EDT发布一个Runnable来修改按钮。

显然,我不应该依赖于AWTEvent按顺序处理。我不能在EDT中等待行为触发,因为任何SwingUtilities.invokeAndWait()都会导致死锁。


1
据我所知并尝试过的,基于OpenGL的3D_API需要使用AWT容器,并且要小心处理http://java.sun.com/products/jfc/tsc/articles/mixing/中提到的在一个容器中放置(意味着JPanel而不是JFrame、JDialog或JWindow)。 - mKorbel
1个回答

5

哪种 WakeupCriterion 用于唤醒你的特殊行为对象?

Java 3D 的源代码包含实用类

com.sun.j3d.utils.behaviors.mouse.MouseBehavior/MouseRotate 

这段内容涉及IT技术,它监听Canvas3D的AWTEvents。你可以选择两种方式之一:
1.使用WakeupOnBehaviorPost的MouseListener 2.使用WakeupOnAWTEvent
以下代码示例可能会有所帮助。
在Behavior.processStimulus方法中通过SwingUtilities.invokeLater来启动Swing组件更新不应该引起任何问题。

感谢您提供关于WakeupOnAWTEvent的提示。查看源代码后,我单独实现了相同的功能;不重复API功能总是很好的。 - parasietje

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接