Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combine Java Swing and Java3D: performance problems with concurrency

I am combining Swing and Java3D together. Manipulations of swing components should be done using the Event Dispatcher Thread, while manipulations of Java3D components should be done in the BehaviourSchedulerThread.

Java3D renders the scene and then executes all of the behavior associated to the scene.

I have a MouseListener enabled on the Canvas3D. Events are posted into the AWT Event queue. I then want to modify the Java3D environment based on these events, so I use a special Behavior where I can post Runnable's to. This makes sure the Runnable's are executed during the Behavior cycle of Java3D (and do not modify anyting during the Render cycle).

Suppose some operations in the Behavior want to modify the Swing model. I then have to post a new Runnable to the EDT.

Is this the correct way to do it?

Using this technique, I experience a lot of problems on a mouse listener. I update a point in my Java3D model in the behaviour, and I update the swing GUI at the same time.

Update: The problem can be more clearly defined as follows:

I have a JButton "spin cube" which has an ActionListener. Once the ActionListener is fired, it pushes the AWTEvent into a Java3D Behavior. Once the Behavior fires, it modifies the Scene graph and then modifies the JButton actionListener and text to become "Stop spinning".

  1. Click on the JButton twice.
  2. The first AWTEvent gets dispatched to SpinActionListener. The cube starts spinning and the JButton actionListener is modified to StopSpinningActionListener.
  3. The second AWTEvent gets dispatched to StopSpinningActionListener. The cube stops spinning and the JButton actionListener is modified to SpinActionListener.

What actually happens is the following:

  1. Click on a JButton twice. Both AWTEvents get dispatched to SpinActionListener. This creates a Runnable to execute inside the J3D Behavior.
  2. The first AWTEvent starts a timer to spin the cube. It then posts a Runnable to the EDT to modify the button.
  3. The second AWTEvent starts a timer to spin the cube. The cube will now spin twice as fast. It then posts a Runnable to the EDT to modify the button.

Obviously, I should not be depending on AWTEvent's getting processed sequentially. I cannot wait in the EDT for the behavior to fire, because any SwingUtilities.invokeAndWait() will then cause a deadlock.

like image 229
parasietje Avatar asked Jan 13 '12 08:01

parasietje


1 Answers

Which WakeupCriterion is used to wake-up your special Behavior object?

Java 3D's source code includes the utility classes

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

which listens to Canvas3D's AWTEvents. One of two alternatives can be chosen:

  1. MouseListener with WakeupOnBehaviorPost or
  2. WakeupOnAWTEvent.

This code sample might be helpful.

Initiating a Swing component update from within the Behavior.processStimulus method via SwingUtilities.invokeLater shouldn't cause any problems.

like image 68
InteractiveMesh Avatar answered Oct 23 '22 03:10

InteractiveMesh