java swing

<!-- @page { size: 21cm 29.7cm; margin: 2cm } P { margin-bottom: 0.21cm } -->



     Swing 是目前 Java 中不可缺少的窗口工具組,是用戶建立圖形化用戶界面( GUI )程序的強大工具。 Java Swing 組件自動產生各種事件來響應用戶行爲。如當用戶點擊按鈕或選擇菜單項目時, Swing 組件會產生一個 ActionEvent Swing 組件會產生許多事件,如 ActionEvents,ChangeEvents,ItemEvents 等,來響應用戶的鼠標點擊行爲,列表框中值的改變,計時器的開始計時等行爲。在 Java Swing 編程中,通過 註冊監聽器 ,我們可以監聽事件源產生的事件,從而在事件處理程序中處理我們所需要處理的用戶行爲。

 

Java Swing 中處理各組件事件的一般步驟是:

1 .   新建一個組件(如 JButton )。

2 .   將該組件添加到相應的面板(如 JPanel )。

3 .   註冊監聽器以監聽事件源產生的事件(如通過 ActionListener 來響應用戶點擊按鈕)。

4 .   定義處理事件的方法(如在 ActionListener 中的 actionPerformed 中定義相應方法)。

 

以上步驟我們可以用多種方法實現。但人們通常用二種方法。第一種方法是隻利用一個監聽器以及多個 if 語句來決定是哪個組件產生的事件;第二種方法是使用多個內部類來響應不同組件產生的各種事件,其具體實現又細分爲兩種方式:一種是匿名內部類,一種是一般內部類。

 

爲了說明如何使用上述三種方法實現事件的處理方法,我們建立一個簡單的應用程序。該程序界面有兩個按鈕,當用戶點擊相應的按鈕,就會彈出一個對話框顯示相應的內容。通過這個簡單的程序,你可以瞭解 Swing 中事情處理的機制,從而實現更多、更復雜的用戶界面程序。

 

首先,我們利用單個監聽器來實現該程序。我們定義一個名爲 Simple1 的類來包括所有代碼。所有的用戶行爲(如點擊按鈕)由一個監聽器 SimpleListenner 中的 actionPerformed 方法來處理。以下是實現代碼:

package org.leno.swing.demo2;

 

/*

  * Simple1.java - 處理事件的第一種方法

  *    在這個例子中,利用一個 ActionListener 來監聽事件源產生的事件

  *    用一些 if 語句來決定是哪個事件源

 */

 

import java.awt.event.*;

import javax.swing.*;

 

public class Simple1 {

       private static JFrame frame ; // 定義爲靜態變量以便 main 使用

       private static JPanel myPanel ; // 該面板用來放置按鈕組件

       private JButton button1 ; // 這裏定義按鈕組件

       private JButton button2 ; // 以便讓 ActionListener 使用

 

       public Simple1() // 構造器 , 建立圖形界面

       {

              // 新建面板

              myPanel = new JPanel();

              // 新建按鈕

              button1 = new JButton( " 按鈕 1" ); // 新建按鈕 1

              button2 = new JButton( " 按鈕 2" );

 

              SimpleListener ourListener = new SimpleListener();

              // 建立一個 actionlistener 讓兩個按鈕共享

              button1 .addActionListener(ourListener);

              button2 .addActionListener(ourListener);

 

              myPanel .add( button1 ); // 添加按鈕到面板

              myPanel .add( button2 );

       }

 

       private class SimpleListener implements ActionListener {

              /*

                * 利用該內部類來監聽所有事件源產生的事件 便於處理事件代碼模塊化

               */

              public void actionPerformed(ActionEvent e) {

                     // 利用 getActionCommand 獲得按鈕名稱

                     // 也可以利用 getSource() 來實現

                     // if (e.getSource() ==button1)

                     String buttonName = e.getActionCommand();

                     if (buttonName.equals( " 按鈕 1" ))

                            JOptionPane. showMessageDialog ( frame , " 按鈕 1 被點擊 " );

                     else if (buttonName.equals( " 按鈕 2" ))

                            JOptionPane. showMessageDialog ( frame , " 按鈕 2 被點擊 " );

                     else

                            JOptionPane. showMessageDialog ( frame , "Unknown event" );

              }

       }

 

       public static void main(String s[]) {

              Simple1 gui = new Simple1(); // 新建 Simple1 組件

              frame = new JFrame( "Simple1" ); // 新建 JFrame

              // 處理關閉事件的通常方法

              frame .addWindowListener( new WindowAdapter() {

                     public void windowClosing(WindowEvent e) {

                            System. exit (0);

                     }

              });

              frame .getContentPane().add( myPanel );

              frame .pack();

              frame .setVisible( true );

       }

}

 

讓我們來看看以上代碼是如何工作的。在 main 方法中,我們定義了一個 JFrame ,然後將面板 Jpanel 添加到窗體中,該面板包括兩個按鈕。相應的變量 Frame,button1,button2 定義在程序的開頭部分。在程序入口 main 方法中,首先新建 Simple1 組件,通過構造器建立用戶 GUI ,定義一個面板 Jpanle, ,增加兩個按鈕,然後利用 JButton.addActionListerner 將兩個按鈕加入到一個活動監聽器 SimpleLister 中,最後,兩個按鈕添加到面板。當 GUI 建立後,我們將面板添加到窗體並顯示結果。當用戶點擊按鈕時,程序調用 actionPerformed 方法,通過 if 語句來判斷是哪一個按鈕被點擊,然後在對話框中顯示相應的內容。

 

利用一個監聽器來處理事件的缺點是,當程序比較複雜時,需要一大串的 if  語句來實現,程序代碼較難閱讀與維護。當然,如果處理的事件較少,這種方式比較簡單。

通過使用匿名內部類可以解決上述存在的問題。使用簡單的匿名內部類作爲 addActionListener 的參數即可。以下是實現代碼:

package org.leno.swing.demo2;

 

/*

  * Simple2.java - 處理事件的第二種方法

  *    在這個例子中,利用匿名內部類來監聽每一個事件源產生的事件

  *    避免使用一些 if 語句來決定是哪個事件源

  */

import java.awt.event.*;

import javax.swing.*;

 

public class Simple2 {

       private static JFrame frame ; // 定義爲靜態變量以便 main 使用

       private static JPanel myPanel ; // 該面板用來放置按鈕組件

       private JButton button1 ; // 這裏定義按鈕組件

       private JButton button2 ; // 以便讓 ActionListener 使用

 

       public Simple2() // 構造器 , 建立圖形界面

       {

              // 新建面板

              myPanel = new JPanel();

              // 新建按鈕

              button1 = new JButton( " 按鈕 1" ); // 新建按鈕 1

              button2 = new JButton( " 按鈕 2" );

 

              // 每一個事件源需要一個監聽器

              // 定義一個匿名內部類來監聽事件源產生的事件

              button1 .addActionListener( new ActionListener() {

                     public void actionPerformed(ActionEvent e) {

                            JOptionPane . showMessageDialog ( frame , " 按鈕 1 被點擊 " );

                     }

              });

 

              button2 .addActionListener( new ActionListener() {

                     public void actionPerformed(ActionEvent e) {

                            JOptionPane . showMessageDialog ( frame , " 按鈕 2 被點擊 " );

                     }

              });

              myPanel .add( button1 ); // 添加按鈕到面板

              myPanel .add( button2 );

       }

 

       public static void main(String s[]) {

              Simple2 gui = new Simple2(); // 新建 Simple2 組件

 

              frame = new JFrame( "Simple2" ); // 新建 JFrame

              // 處理關閉事件的通常方法

              frame .addWindowListener( new WindowAdapter() {

                     public void windowClosing(WindowEvent e) {

                            System. exit (0);

                     }

              });

              frame .getContentPane().add( myPanel );

              frame .pack();

              frame .setVisible( true );

       }

}

 

使 用匿名內部類同樣存在許多另外的問題。首先,根據組件在代碼中被定義的不同位置,類的定義以及處理事件的代碼將分散在程序的各個部分,不是集中在一塊,同 樣不便於閱讀與維護。各事件的處理全部由嵌套的程序塊組成,視覺上很難定位程序代碼。如果事件處理程序比較複雜,內部類中的代碼將變得很長,你將找不到相 應的組件定義位置。最後,當工具欄、菜單欄目等需要處理同樣的用戶行爲時,該方法將使代碼更難維護。

我們使用一般的命名內部類可以解決以上許多問題。所有的事件處理方法都集中在一塊,並且都具有有意義的名稱,程序非常容易閱讀與維護。單個的事件處理程序也可以被工具欄、菜單欄等重複使用,以下是實現代碼:

package org.leno.swing.demo2;

 

/*

  * Simple3.java - 處理事件的第三種方法

 *    For this example, we will use inner member classes to

  *    在這個例子中,利用一般內部類來監聽每個事件源產生的事件

  *    該方法避免了第二種方法中由於使用匿名內部類而導致的代碼混亂

  *    便於集中處理事件代碼

  *    每一個 Hander 可以被工具欄或菜單多次使用

  */

import java.awt.event.*;

import javax.swing.*;

 

public class Simple3 {

       private static JFrame frame ; // 定義爲靜態變量以便 main 使用

       private static JPanel myPanel ; // 該面板用來放置按鈕組件

       private JButton button1 ; // 這裏定義按鈕組件

       private JButton button2 ; // 以便讓 ActionListener 使用

 

       // 利用一般內部類來監聽每一個事件源產生的事件如 (button1, button2)

       private class Button1Handler implements ActionListener {

              public void actionPerformed(ActionEvent e) {

                     JOptionPane . showMessageDialog ( frame , " 按鈕 1 被點擊 " );// 彈出框

              }

       }

 

       private class Button2Handler implements ActionListener {

              public void actionPerformed(ActionEvent e) {

                     JOptionPane. showMessageDialog ( frame , " 按鈕 2 被點擊 " );

              }

       }

 

       public Simple3() // 構造器 , 建立圖形界面

       {

              // 新建面板

              myPanel = new JPanel();

              // 新建按鈕

              button1 = new JButton( " 按鈕 1" ); // 新建按鈕 1

              button2 = new JButton( " 按鈕 2" );

 

              // 對每一個組件註冊監聽內部類

              button1 .addActionListener( new Button1Handler());

              button2 .addActionListener( new Button2Handler());

 

              myPanel .add( button1 ); // 添加按鈕到面板

              myPanel .add( button2 );

       }

 

       public static void main(String s[]) {

              Simple3 gui = new Simple3(); // 新建 Simple3 組件

 

              frame = new JFrame( "Simple3" ); // 新建 JFrame

              // 處理關閉事件的通常方法

              frame .addWindowListener( new WindowAdapter() {

                     public void windowClosing(WindowEvent e) {

                            System. exit (0);

                     }

              });

 

              frame .getContentPane().add( myPanel );

              frame .pack();

              frame .setVisible( true );

       }

}

 

以上分析了在 Java Swing 中三種事件處理的方式,其中利用一般內部類來實現的方法,從代碼書寫、閱讀、維護以及程序的可擴展性角度來看,最爲值得推薦。


 

發佈了27 篇原創文章 · 獲贊 3 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章