2

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)
4

1 に答える 1

4

Swingコンポーネントはスレッドセーフではありません。すでに表示された後にSwingコンポーネントを変更するものはすべて、いわゆるイベントディスパッチスレッド(EDT)で実行する必要があります。これを達成するために、Swingはあなたに次の機能を付与します。

それらのうちの2つは、コードの実行に役立ちます。

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

彼らの目的は彼らの名前から来ています。三つ目は

SwingUtilities.isEventDispatchThread()

これがを返す場合はtrue、すでにEDTに入っており、コードを直接実行できます。

invokeAndWaitEDTから直接呼び出された場合は例外がスローされることに注意してください(invokeLaterそうしませんが、それでもそうすることはお勧めしません)。したがって、EDTとサイドスレッドの両方から呼び出される可能性のあるコードは、次のように記述する必要があります。 :

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

単純さと読みやすさの目的で、メソッドに内部コードを抽出することができます。

于 2011-04-22T12:44:01.637 に答える