有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java/swing:JSlider。setValue正在阻塞

我打电话给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)

共 (1) 个答案

  1. # 1 楼答案

    Swing组件不是线程安全的。任何在Swing组件显示后修改它的内容都必须在所谓的事件调度线程(EDT)中执行。为了实现这一点,Swing为您提供了以下功能:

    其中两个用于代码执行:

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

    他们的目的来自他们的名字。三是

    SwingUtilities.isEventDispatchThread()
    

    如果返回true,那么您已经在EDT中,可以直接执行代码

    请注意,如果直接从EDT调用invokeAndWait将引发异常(invokeLater将不会,但仍不建议这样做),因此可以从EDT和侧线程调用的代码应编写如下:

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

    为了简单易读,可以将内部代码提取到方法中