java / swing: JSlider.setValue блокирует - PullRequest
2 голосов
/ 22 апреля 2011

Мой вызов JSlider.setValue иногда блокирует поток, что приводит к тупиковой ситуации всего приложения.

здесь - трассировка стека блокирующего потока.

Thread [RenderThread] (Suspended)   
JSlider(Component).getMousePosition() line: not available [local variables unavailable] 
SynthSliderUI.calculateThumbLocation() line: not available [local variables unavailable]    
BasicSliderUI$Handler.stateChanged(ChangeEvent) line: not available 
DefaultBoundedRangeModel.fireStateChanged() line: not available [local variables unavailable]   
DefaultBoundedRangeModel.setRangeProperties(int, int, int, int, boolean) line: not available    
DefaultBoundedRangeModel.setValue(int) line: not available  
JSlider.setValue(int) line: not available   
TimeLine.setTime(double) line: 422  
GLFrame.display() line: 302 
GLFrame$2.renderCallback() line: 188    
LWJGLBinding$1.paintGL() line: 49   
LWJGLBinding$1(AWTGLCanvas).paint(Graphics) line: 314   
LWJGLBinding$1(AWTGLCanvas).update(Graphics) line: 343  
GLFrame$2(LWJGLBinding).startRendering() line: 78   
GLFrame$3.run() line: 267   

это, кажется, связано с внешним видом и ощущением нимба, потому что я не вижу его по умолчанию.

    try 
    {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
    } 
    catch (Exception e) 
    {
        e.printStackTrace();
    }

редактирование: с invokeLater я получаю это исключение:

at javax.swing.plaf.synth.SynthTreeUI.paint(Unknown Source)
at javax.swing.plaf.synth.SynthTreeUI.update(Unknown Source)
at javax.swing.JComponent.paintComponent(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintToOffscreen(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
at javax.swing.RepaintManager.paint(Unknown Source)
at javax.swing.JComponent._paintImmediately(Unknown Source)
at javax.swing.JComponent.paintImmediately(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.seqPaintDirtyRegions(Unknown Source)
at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$000(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

1 Ответ

4 голосов
/ 22 апреля 2011

Компоненты Swing не являются поточно-ориентированными.Все, что изменяет компонент Swing после того, как оно уже показано, должно выполняться в так называемом потоке диспетчеризации событий (EDT).Для этого Swing предоставляет вам следующие функции:

Две из них служат для выполнения кода:

SwingUtilities.invokeLater(Runnable)
SwingUtilities.invokeAndWait(Runnable)

Их назначение исходит из их названия.Третье - это

SwingUtilities.isEventDispatchThread()

Если это возвращает true, то вы уже в EDT и можете выполнять код напрямую.

Обратите внимание, что invokeAndWait вызовет исключение, еслион вызывается напрямую из EDT (invokeLater не будет, но делать это не рекомендуется), поэтому код, который можно вызывать как из EDT, так и из бокового потока, должен быть записан следующим образом:

if (SwingUtilities.isEventDispatchThread()) {
    // code
} else {
    SwingUtilities.invokeLater(new Runnable () {
        public void run () {
            // code
        }
    });
}

В целях простоты и удобочитаемости вы можете извлечь внутренний код для метода.

...