如果我使用 使用单独的线程从 Java 中充斥 Swing 事件队列SwingUtilities.invokeLater(..)
,则事件调度线程无法跟上步伐,事件队列填满并且应用程序运行缓慢。
例如......在下面的例子中,我只能看到屏幕上显示的几个整数(mac os-x yosemite,java 8 update 25):
import javax.swing.*;
import java.awt.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.IntStream;
public class SwingForcePaintingQuestion {
public static void main(String[] args) throws InterruptedException {
final AtomicReference<JLabel> labelRef = new AtomicReference<>();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame("Frame42");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(600, 400));
frame.getContentPane().setLayout(new BorderLayout());
JLabel label = new JLabel("Hello");
label.setHorizontalAlignment(SwingConstants.CENTER);
frame.add(label, BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
labelRef.set(label);
}
});
while (labelRef.get() == null) {
Thread.sleep(1);
}
Thread.sleep(1000);
System.out.println("Starting filling the EventQueue");
int start = 1;
int endExclusive = 10000000;
IntStream.range(start, endExclusive).forEach(value ->
SwingUtilities.invokeLater(() -> {
labelRef.get().setText(value + "");
})
);
SwingUtilities.invokeLater(() -> labelRef.get().setText("Done. Did you see all values between " + start + " and " + endExclusive + "?"));
}
}
有没有办法“放慢速度”,这样我才能真正看到 GUI 中的每一个变化?调用标签repaint
后在某处调用某种方法?setText(..)
疯狂的闪烁是完全可以的,因为我希望我的眼睛比像素可以改变的“慢”。目前这个例子表现得“奇怪”,最后我看到一个特定的数字,比如让我们说 1070201 一整秒,然后我看到 1531452 一整秒。
当然,我可以使用SwingUtilities.invokeAndWait(..)
而不是为SwingUtilities.invokeLater(..)
“生产”主线程建立背压,以防止“填满”事件队列。难道没有别的办法了吗?