Объединение Java Swing и Java3D: проблемы с производительностью с помощью concurrency

Я комбинирую Swing и Java3D вместе. Манипуляции компонентов качания должны выполняться с использованием потока диспетчера событий, в то время как манипуляции с компонентами Java3D должны выполняться в файле BehaviourSchedulerThread.

Java3D создает сцену, а затем выполняет все поведение, связанное с сценой.

У меня есть MouseListener включен на Canvas3D. События отправляются в очередь событий AWT. Затем я хочу изменить среду Java3D на основе этих событий, поэтому я использую специальное поведение, в котором я могу отправить Runnable. Это гарантирует, что Runnable выполняются во время цикла Behavior Java3D (и не изменяют значение во время цикла Render).

Предположим, что некоторые операции в Поведении хотят изменить модель Swing. Затем я должен опубликовать новый Runnable в EDT.

Правильно ли это делается?

Используя эту технику, я испытываю массу проблем у слушателя мыши. Я обновляю точку в своей модели Java3D в поведении, и одновременно обновляю графический интерфейс swing.

Обновление: Проблема может быть более четко определена следующим образом:

У меня есть JButton "спиновый куб", который имеет ActionListener. Как только ActionListener уволен, он подталкивает AWTEvent к Java3D Behavior. Когда срабатывает Поведение, он изменяет график сцены, а затем модифицирует JLutton actionListener и текст, чтобы стать "Stop spinning".

  • Дважды нажмите на JButton.
  • Первый AWTEvent отправляется в SpinActionListener. Куб начинает вращаться, и JButton actionListener изменяется на StopSpinningActionListener.
  • Второй AWTEvent отправляется в StopSpinningActionListener. Куб перестает вращаться, и JButton actionListener изменяется на SpinActionListener.

На самом деле происходит следующее:

  • Дважды нажмите JButton. Оба AWTEvent отправляются в SpinActionListener. Это создает Runnable для выполнения внутри J3D-поведения.
  • Первый AWTEvent запускает таймер для вращения куба. Затем он отправляет Runnable в EDT для изменения кнопки.
  • Второй AWTEvent запускает таймер для вращения куба. Куб теперь будет вращаться в два раза быстрее. Затем он отправляет Runnable в EDT для изменения кнопки.

Очевидно, что я не должен зависеть от того, как AWTEvent обрабатывается последовательно. Я не могу ждать в EDT, чтобы поведение срабатывало, потому что любой SwingUtilities.invokeAndWait() будет вызывать тупик.

Ответ 1

Какой WakeupCriterion используется для пробуждения вашего специального объекта Behavior?

Исходный код Java 3D включает классы утилиты

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

который прослушивает Canvas3D AWTEvents. Можно выбрать один из двух вариантов:

  • MouseListener с WakeupOnBehaviorPost или
  • WakeupOnAWTEvent.

Этот пример кода может оказаться полезным.

Инициирование обновления компонента Swing из метода Behavior.processStimulus с помощью SwingUtilities.invokeLater не должно вызывать никаких проблем.