0

を使用して別のスレッドで 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(..)「生成」メイン スレッドへのバックプレッシャーを使用して確立することもできます。他の方法はありませんか?

4

0 に答える 0