2

実行に時間がかかるメソッドがあります。それをlongTime()と呼びましょう。

このメソッドは、ボタンのアクションリスナーから呼び出されます。

"Please wait.."このメソッドの実行中にメッセージを表示したい。

問題は、Jframeが応答しないことです。スタックしているか、何かを待っているようです。

重要な注意: の実行時間はlongTime()異なる場合があります。この問題は、2〜3秒以上かかる場合にのみ発生します。

私はこれらすべてを実行しようとしましinvokeLateたが、それは役に立ちませんでした。

SwingUtilities.invokeLater(new Runnable() {
  @Override
  public void run() {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
    JLabel label = new JLabel("Please wait...");
    label.setFont(new Font("Serif", Font.PLAIN, 25));
    frame.getContentPane().add(label, BorderLayout.CENTER);
    frame.setLocationRelativeTo(null);
    frame.setUndecorated(true);
    frame.pack();
    frame.setAlwaysOnTop(true);
    frame.setVisible(true);
    try{            
      longTime();  //HERE IS THE FUNCTION THAT TAKES A LONG TIME  
    }catch(Exception e){   }
    frame.dispose();  //AFTER THE LONG FUNCTION FINISHES, DISPOSE JFRAME        
  } 
});

これを修正する方法のアイデアはありますか?

4

5 に答える 5

3
  • JLayer (Java7)based onJXLayer (Java6)またはGlasspaneを使用する方法と、 JLabel(with intermediate Icon) を使用する方法の 2 つがあります。

    1. からSwingWorker

    2. (最も簡単) from Runnable.Thread(Swing GUI への出力は でラップする必要がありますinvokeLater)

  • Swing の Concurency に注意してください。すべての変更は EDT で行う必要があります。

  • 車輪を再発明しないでください、@camickrによるコード例

于 2013-02-11T08:53:10.790 に答える
3

GUI スレッド ( Event Dispatch Thread ) がブロックされるのを防ぐために、時間のかかるタスクはすべて別のスレッドで実行する必要があります。SwingWorkerオブジェクトを使用して長いタスクを実行し、完了時にアクションを実行することを検討することをお勧めします。

このテーマの詳細については、http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.htmlを参照してください。

于 2013-02-11T08:50:27.503 に答える
2

簡単な例でmKorbelとDucanの推奨事項(両方に+1)を強調しています...

public class RunLongTime {

    public static void main(String[] args) {
        new RunLongTime();
    }

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

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public interface WorkMonitor {

        public void updateProgress(float progress);
        public void done();

    }

    public class TestPane extends JPanel implements WorkMonitor {

        private JLabel message;
        private JButton button;

        public TestPane() {
            message = new JLabel("Click to get started");
            button = new JButton("Start");
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.insets = new Insets(2, 2, 2, 2);
            add(message, gbc);
            add(button, gbc);

            button.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    button.setEnabled(false);
                    message.setText("Getting started...");
                    BackgroundWorker worker = new BackgroundWorker(TestPane.this);
                    worker.execute();
                }
            });
        }

        @Override
        public void updateProgress(float progress) {
            message.setText("Please wait..." + NumberFormat.getPercentInstance().format(progress));
        }

        @Override
        public void done() {
            message.setText("All done...");
            button.setEnabled(true);
        }

    }

    public class BackgroundWorker extends SwingWorker<Void, Float> {

        private WorkMonitor monitor;

        public BackgroundWorker(WorkMonitor monitor) {
            this.monitor = monitor;
        }

        @Override
        protected void done() {
            monitor.done();
        }

        @Override
        protected void process(List<Float> chunks) {
            monitor.updateProgress(chunks.get(chunks.size() - 1));
        }

        @Override
        protected Void doInBackground() throws Exception {
            for (int index = 0; index < 1000; index++) {
                Thread.sleep(125);
                publish((float)index / 1000f);
            }
            return null;
        }

    }

}
于 2013-02-11T09:14:33.180 に答える
1

別のスレッドを生成し、longTime()タスクを別のスレッドで実行する必要があります。invokeLater()を呼び出すと、ブロックしたくないUIスレッドで実行されます。

次のコードを検討してください。

    final JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
    JLabel label = new JLabel("Please wait...");
    label.setFont(new Font("Serif", Font.PLAIN, 25));
    frame.getContentPane().add(label, BorderLayout.CENTER);
    frame.setLocationRelativeTo(null);
    frame.setUndecorated(true);
    frame.pack();
    frame.setAlwaysOnTop(true);
    frame.setVisible(true);

    new Thread(new Runnable() {
        @Override
        public void run() {
        try{            
            longTime();  //HERE IS THE FUNCTION THAT TAKES A LONG TIME  
        }catch(Exception e){   }
            frame.dispose();     //AFTER THE LONG FUNCTION FINISHES, DISPOSE JFRAME     
        } 
        }).start();

新しく生成されたスレッドからデータモデルを更新したい場合があります。これは、SwingUtilities.invokeLater()を使用するのに適切な場所です。この新しいスレッドでモデルを更新しないでください。UIコンポーネントのモデルは、UIスレッドでのみ更新する必要があります。後で呼び出すと、まさにそれが行われます。

于 2013-02-11T08:45:49.847 に答える
1

longTime()単に新しいスレッドを呼び出すだけです。

new Thread(){ public void run() {longTime();}}.start();
于 2013-02-11T08:47:12.530 に答える