0

EDT 内で実行されるメソッドがあります。それは次のようなものです:

myMethod()
{
  System.out.prinln(SwingUtilities.isEventDispatchThread());

  for (int i = 0; i < 10; i++)
  {
   Thread.sleep(3000);
   someJPanel.remove(otherJPanel);
  }
}

私が予想したこと: 10 個の JPanel が親から 1 つずつ削除され、各削除の間に 3 秒間の休止があります...

実際に起こったこと: 10 個の要素すべてが一度に削除された後、すべてが 30 秒間フリーズしました。

コンソールの行は常に true でした (SwingUtilities.isEventDispatchThread())。

これはすべて EDT で行っているのに、変更がすぐに反映されないのはなぜですか? メソッドが最初に最後に到達するのを待つのはなぜですか?

削除の間に 3 秒の遅延を発生させるには、コードをどのように変更すればよいですか?

4

2 に答える 2

7

Swing は単一のスレッドを使用してイベントをディスパッチし、再描画要求を処理します。このスレッドをブロックすると、EDT によるこれらの再描画要求の処理が停止され、UI が「停止」したように見えます。

代わりに、 a のようなものを使用しjavax.swing.Timerて遅延を挿入し、アクションを実行します。これにより、EDT 内でアクションが実行されますが、バックグラウンド スレッドで待機します。

詳細については、 The Event Dispatching Threadをお読みください...

タイマーの例で更新

public class SlowDecline {

    public static void main(String[] args) {
        new SlowDecline();
    }
    private TestPane last;

    public SlowDecline() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                TestPane parent = new TestPane(Color.RED);
                TestPane tp = add(parent, Color.BLUE);
                tp = add(tp, Color.GREEN);
                tp = add(tp, Color.CYAN);
                tp = add(tp, Color.LIGHT_GRAY);
                tp = add(tp, Color.MAGENTA);
                tp = add(tp, Color.ORANGE);
                tp = add(tp, Color.PINK);

                last = tp;

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(parent);
                frame.setSize(200, 200);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                Timer timer = new Timer(1000, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        if (last != null) {
                            Container parent = last.getParent();
                            if (parent != null) {
                                parent.remove(last);
                                parent.repaint();
                                if (parent instanceof TestPane) {
                                    last = (TestPane) parent;
                                }
                            } else {
                                last = null;
                            }
                        } else {
                            (((Timer)e.getSource())).stop();
                        }
                    }
                });
                timer.setRepeats(true);
                timer.setCoalesce(true);
                timer.start();
            }
        });
    }

    public TestPane add(TestPane parent, Color color) {

        TestPane child = new TestPane(color);
        parent.add(child);
        return child;
    }

    public class TestPane extends JPanel {

        public TestPane(Color background) {
            setLayout(new BorderLayout());
            setBorder(new EmptyBorder(10, 10, 10, 10));
            setBackground(background);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(50, 50);
        }
    }
}
于 2013-03-01T02:10:56.760 に答える
4

これは、UI スレッドが画面の描画とイベントの処理を担当するためです。UI スレッドをスリープ状態にすると、それ以上描画やイベント処理を行うことができなくなります。スレッドがペイントを再開すると、すべてのパネルが既に削除されています。

この URL は、 Swing でスレッド化を処理する方法について非常に包括的です。

パネルを削除するスレッドを作成することをお勧めします。

(未テスト)

Thread t = new Thread() {
   @Override
   public void run() {  // override the run() for the running behaviors
     for (int i = 0; i < 10; i++)
     {
        Thread.sleep(3000);
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
           someJPanel.remove(...);
          });
     }
   }
};
t.start();  // call back run()
于 2013-03-01T02:13:46.043 に答える