2010年7月2日 星期五

事件處理的重複註冊問題


起初我將各個功能視窗的生成,分別製作成 method 以方便管理,並自然而然在各 method 內幫元件進行事件處理的觸發註冊,然而彼此視窗間,時常會有返回先前視窗的動作,此時很容易會產生事件處理重複註冊的 Bug。


為求理解上的方便,故我們直接設定按下按鈕時,會先釋放舊有的視窗並重新產生原本的新視窗,做出類似視窗間重複返回的動作,如下列程式:

public class gui extends JFrame{
     Container cp=getContentPane();  //控制容器
    JButton btn1 = new JButton();

     public void A(){

           ......                                                                     //視窗版面的設置
           btn1..addActionListener(new action());}       //向action註冊按鈕的事件處理
}


public class action implements ActionListener{
     public void actionPerformed(ActionEvent e) {

          JButton btn= (JButton) e.getSource();
          if(btn==gui.btn1){                                             //按下btn1時

               gui.cp.removeAll();                                     //釋放容器內的所有元件
               gui.dispose();                                             //釋放視窗

               gui.A();}                                                       //呼叫 A  method 重新建立視窗
     }
}

視窗看似只有一個,但在第一次按下後重新產生視窗的同時,卻發生 btn1 重複註冊的問題,導致再次按下按鈕時,除了觸發當前視窗的按鈕事件之外,也同時觸發前一個視窗的按鈕事件,造成事件被重複執行兩次。若重複按下按鈕,則事件執行次數會有如 Binary Tree 般增加。

為此避免產生重複註冊的問題,故將上述程式修改為:

 public class gui extends JFrame{
     Container cp=getContentPane();  //控制容器
    JButton btn1 = new JButton();

     
     public gui(){
          btn1..addActionListener(new action());}         //該物件產生的同時就先行註冊

     public void A(){

           ......                                                                     //視窗版面的設定

}


public class action implements ActionListener{
     public void actionPerformed(ActionEvent e) {

          JButton btn= (JButton) e.getSource();
          if(btn==gui.btn1){                                             //按下btn1時

               gui.cp.removeAll();                                     //釋放容器內的所有元件
               gui.dispose();                                             //釋放視窗

               gui.A();}                                                       //呼叫 A  method 重新建立視窗
     }
}

其實不侷限於上述方法,重點在於如何避免事件處理重複註冊的問題,除了物件產生時先行註冊之外,也可以在產生視窗的同時,判斷該事件是否有被註冊過,進而避免重複註冊的問題。

參考資料:

沒有留言:

張貼留言