JButton事件處理中UI的重新整理問題

來源:互聯網
上載者:User

註:根據yigemaser、JFML、CrazyJavar的建議更新,對三位的協助表示感謝!

在寫UI應用時,通常會在一些事件處理的過程中,尤其當這個處理比較耗時的時候,希望能夠及時把一些進度資訊顯示給使用者。這時通常大家都會使用一個文本控制項來顯示這些進度資訊。比如下面的程式中,有一個JTextPane和JButton,在JButton中的action事件中需要進行一些耗時的處理,例子程式中使用了Thread.sleep()使當前線程休眠3秒來類比耗時的操作。action事件處理分為3步,我們希望及時把當前的進度顯示在JTextPane上。
代碼如下:

  1. package bruce.test;
  2. import javax.swing.*;
  3. import java.awt.Container;
  4. import java.awt.BorderLayout;
  5. import java.awt.Dimension;
  6. import java.awt.event.WindowAdapter;
  7. import java.awt.event.ActionListener;
  8. import java.awt.event.ActionEvent;
  9. /**
  10.  * 事件處理過程中UI的重新整理
  11.  * @author Bruce
  12.  * @version 1.0
  13.  */
  14. public class TestUIUpdate2 {
  15.   public TestUIUpdate2() {
  16.     TestUIUpdate2Frame frame = new TestUIUpdate2Frame();
  17.     frame.pack();
  18.     frame.setVisible(true);
  19.   }
  20.   public static void main(String[] args) {
  21.     new TestUIUpdate2();
  22.   }
  23. }
  24. class TestUIUpdate2Frame extends JFrame {
  25.   JTextPane pane = new JTextPane();
  26.   JButton button = new JButton("action...");
  27.   TestUIUpdate2Frame() {
  28.     init();
  29.     this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  30.     button.addActionListener(new ActionListener() {
  31.       public void actionPerformed(ActionEvent e){
  32.                 try {
  33.                     pane.setText("step one..."); 
  34.                     Thread.sleep(3000);
  35.                     pane.setText("\nstep two..."); 
  36.                     Thread.sleep(3000);
  37.                     pane.setText("\nfinished."); 
  38.                     Thread.sleep(3000);
  39.                 }
  40.                 catch (InterruptedException ie) {
  41.                   //ignored
  42.                 }
  43.       }
  44.     });
  45.   }
  46.   private void init() {
  47.     pane.setPreferredSize(new Dimension(300,200));
  48.     Container content = getContentPane();
  49.     content.setLayout(new BorderLayout());
  50.     content.add(pane, BorderLayout.CENTER);
  51.     content.add(button, BorderLayout.SOUTH);
  52.   }
  53. }

但在實際運行過程中可以發現,點擊JButton後,JTextPane並不能及時更新,而是在整個JButton的action事件處理完畢後才能顯示出最後的資訊。為什麼會出現這種情況呢?因為在處理JButton的action事件程序中,雖然更新了JTextPane的內容,但由於JButton的事件處理是在當前main線程中運行,雖然JTextPane更新了內容,但沒有得到重新整理顯示的執行機會。

解決這個問題的方法非常簡單,只需要把JButton的action處理代碼放入一個新的線程,然後啟動這個線程。另外,由於Swing的操作大部分是非安全執行緒的,所以對Swing介面的重新整理也單獨放在一個線程,並調用SwingUtilities.invokeLater()執行。這樣action事件處理、更新JTextPane的介面和main主線程就分別運行在各自的線程中,都可以及時得到執行。JButton的

  1. actionPerformed(ActionEvent e)的處理代碼修改如下:
  2. [code]    button.addActionListener(new ActionListener() {
  3.       public void actionPerformed(ActionEvent e){
  4.           try
  5.           {
  6.             new Thread() {
  7.               public void run() {
  8.                 try {
  9.                     showMessage("step one..."); 
  10.                     Thread.sleep(3000);
  11.                     showMessage("\nstep two..."); 
  12.                     Thread.sleep(3000);
  13.                     showMessage("\nfinished."); 
  14.                     Thread.sleep(3000);
  15.                 }
  16.                 catch (InterruptedException ie) {
  17.                   //ignored
  18.                 }
  19.               }
  20.             }.start();
  21.               
  22.           }
  23.           catch (Exception ex)
  24.           {
  25.             ex.printStackTrace();              
  26.           }
  27.       }
  28.     });

showMessage方法如下:

  1.   private void showMessage (final String msg) {
  2.     SwingUtilities.invokeLater(new Runnable() {
  3.     public void run() {
  4.     pane.setText(pane.getText() + msg); 
  5.     }
  6.     });
  7.   }

大家可以測試回合觀察效果。這樣也使介面更加友好,因為如果不把action的處理代碼放在一個單獨的線程中,使用者點擊JButton後,介面就停止一切響應,直到action處理代碼執行完畢。大家可以擴充這種方法,允許使用者隨時停止該耗時的操作,使介面更加友好。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.