を使用して別のスレッドで Java から Swing イベント キューをフラッディングするとSwingUtilities.invokeLater(..)
、イベント ディスパッチ スレッドが追いつかなくなり、EventQueue がいっぱいになり、アプリケーションの動作が遅くなります。
たとえば...次の例では、画面に表示されている整数の数しか表示されていません(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(..)
私の目はピクセルの変化よりも「遅い」と予想されるため、激しいちらつきはまったく問題ありません。現時点では、この例は「奇妙な」動作をしており、最後に 1 秒間 1070201 のような特定の数値が表示され、次に 1 秒間 1531452 が表示されます。
もちろん、イベント キューが「いっぱい」になるのを防ぐために、SwingUtilities.invokeAndWait(..)
代わりにSwingUtilities.invokeLater(..)
「生成」メイン スレッドへのバックプレッシャーを使用して確立することもできます。他の方法はありませんか?