我对 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 的外观和感觉有关,因为 i 不会在默认的外观和感觉中发生。
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)
最佳答案
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
}
});
}
为了简单性和可读性,您可以将内部代码提取到方法中。
关于java/swing : JSlider. setValue 阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5754555/