【问题标题】:java/swing: JSlider.setValue is blockingjava/swing: JSlider.setValue 被阻塞
【发布时间】:2011-04-22 10:34:13
【问题描述】:

我对 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   

这似乎与 nimbus 外观和感觉有关,因为我不会在默认外观中发生。

    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)

【问题讨论】:

  • 确保在 EDT 上调用 setValue
  • 好的,谢谢。推荐的方法是什么?
  • SwingUtilites.invokeLater(new Runnable(){ public void run(){ / *Your code */ }})
  • 好的,谢谢!这样就解决了问题!
  • @Frozen,您应该将其移至答案,以便@clamp 可以接受。

标签: java swing jslider


【解决方案1】:

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
        }
    });
}

为了简单和可读性,您可以将内部代码提取到方法中。

【讨论】:

  • +1 好答案。这里只是一个细节,当您使用 SwingUtilities.invokeLater(Runnable) 时,您不需要确保它不在 EDT 上运行,而使用 SwingUtilities.invokeAndWait(Runnable) 时必须这样做。只有invokeAndWait 才会抛出异常。最好检查一下,因为您不会导致代码进入队列末尾。
  • 谢谢。实际上,即使我使用invokeLater,我也会在启动时遇到您所说的异常。在我的原始帖子中查看我的编辑
  • @Boro 谢谢,更正了。 @clamp 您能否发布一个异常本身,而不仅仅是堆栈跟踪?
  • 好吧,异常本身只是一个空指针异常,从我发布的堆栈开始。
  • 您似乎还有其他 Swing 修改方法,这些方法不是从 EDT 调用的(请参阅 bugs.sun.com/bugdatabase/view_bug.do?bug_id=4524304)。请检查是否属实。
猜你喜欢
  • 2012-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多