亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Java 圖形用戶界面設計

2019-11-18 14:07:49
字體:
來源:轉載
供稿:網友

  作為一個 java 程序員,從論壇上感受到使用 Java 開發程序的人越來多,心中不免欣慰。但是,同樣是從論壇中,看到多數人提到 Java 就以為是網絡開發——不是這樣的,Java 也可以開發應用程序,而且可以開發出漂亮的圖形用戶界面的應用程序,也就是 Windows/XWindow 應用程序。因此,我寫下這篇文章,希望能帶你進入Java 圖形用戶界面設計之門。

   一. AWT 和 SWING

  AWT 和 SWING 是 Java 設計 GUI 用戶界面的基礎。與 AWT 的重量級組件不同,Swing 中大部分是輕量級組件。正是這個原因,Swing 幾乎無所不能,不但有各式各樣先進的組件,而且更為美觀易用。所以一開始使用 AWT 的程序員很快就轉向使用 Swing 了。

  那為什么 AWT 組件沒有消亡呢?因為 Swing 是架構在 AWT 之上的,沒有 AWT 就沒有 Swing。所以程序員可以根據自己的習慣選擇使用 AWT 或者是 Swing。但是,最好不要二者混用——除開顯示風格不同不說,還很可能造成層次 (Z-Order) 錯亂,比如下例:

/**
* TestPanels.java
* @author Fancy
*/
import javax.swing.*;
import java.awt.*;

public class TestPanels extends JFrame {

 public TestPanels() {
  setDefaultCloSEOperation(EXIT_ON_CLOSE);

  JPanel panel = new JPanel();
  for (int i = 0; i < 2; i++) {
   panel.add(new JButton("Button 00" + i));
  }

  JTextArea textArea = new JTextArea(5, 15);
  textArea.setLineWrap(true);
  JScrollPane scrollPane = new JScrollPane(textArea);
  getContentPane().add(panel, BorderLayout.NORTH);
  getContentPane().add(scrollPane, BorderLayout.CENTER);

  pack();
 }

 public static void main(String[] args) {
  TestPanels tp = new TestPanels();
  tp.show();
 }

}

  運行這個程序,并用鼠標拖動那個名為“cover”的子窗口,我們會發現一個非常有趣的現象,如圖:

Java 圖形用戶界面設計(圖一)

  顯然 cover 子窗口是在 controls 子窗口之上的,但是它只罩蓋住了 Swing Button,沒有罩蓋住 AWT Button。再看一會兒,你是不是有這樣一種感覺:Swing Button 是“畫”上去的,而 AWT Button 則是“貼”上去的。這就是二者混用造成層次錯亂的一個例子。

  Swing 組件有美觀、易用、組件量大等特點,也有缺點——使用 Swing 組件的程序通常會比使用 AWT 組件的程序運行更慢。但是大家都還是更喜歡用 Swing 組件,原因何在?因為隨著計算機硬件的升級,一點點速度已經不是問題。相反的,用戶更需要美觀的用戶界面,開發人員則更需要易用的開發組件。

  ——好,我這就來教你使用 Swing 組件開發圖形用戶界面的 Java 應用程序。   二. 框架、監聽器和事件

  框架 (Frame) 是 Java 圖形用戶界面的基礎,它就是我們通常所說的窗口,是 Windows/XWindow 應用程序的典型特征。說到 Windows/XWindow,大家很輕易聯想到“事件 (Event) 驅動”。Java 的圖形用戶界面正是事件驅動的,并且由各種各樣的監聽器 (Listener) 負責捕捉各種事件。

  假如我們需要對某一個組件的某種事件進行捕捉和處理時,就需要為其添加監聽器。比如,我們要在一個窗口 (JFrame) 激活時改變它的標題,我們就需要為這個窗口 (JFrame 對象) 添加一個可以監聽到“激活窗口”這一事件的監聽器——WindowListener。

  怎么添加監聽器呢?這通常由組件類提供的一個 addXXXXXListener 的方法來完成。比如 JFrame 就提供有 addWindowListener 方法添加窗口監聽器 (WindowListener)。

  一個監聽器經常不只監聽一個事件,而是可以監聽相關的多個事件。比如 WindowListener 除了監聽窗口激活事件 (windowActivate) 之外,還可以監聽窗口關閉事件 (windowClosing) 等。那么這些事件怎么區分呢?就靠重載監聽器類 (Class) 的多個方法 (Method) 了,監聽器監聽到某個事件后,會自動調用相關的方法。我們只要重載這個方法,就可以處理相應的事件了。

  不妨先看一個例子:

/**
* TestFrame.java
* @author Fancy
*/
import javax.swing.*;
import java.awt.event.*;

public class TestFrame extends JFrame {

 PRivate int counter = 0;

 public TestFrame() {
  /* 使用匿名類添加一個窗口監聽器 */
  addWindowListener(new WindowAdapter() {
  public void windowClosing(WindowEvent e) {
   System.out.println("Exit when Closed event");
   System.exit(0); //退出應用程序
  }

  public void windowActivated(WindowEvent e) {
   setTitle("Test Frame " + counter++); // 改變窗口標題
  }
 });

 setResizable(false); // 設置窗口為固定大小
 setSize(200, 150);
}

 public static void main(String[] args) {
  TestFrame tf = new TestFrame();
  tf.show();
 }

}


  這個例子中,我們設計了一個窗口類(public class TestFrame extends JFrame { ...),并且為這個窗口添加了一個窗口監聽器 (addWindowListener(new WindowAdapter() ...)。而我們添加的這個窗口監聽器主要監聽了兩個事件:窗口關閉 (public void windowClosing(WindowEvent e) ...) 和窗口激活 (public void windowActivated(WindowEvent e) ...)。在窗口關閉事件中我們退出了整個應用程序(System.exit(0);),而在窗口激活事件中,我們改變了窗口的標題 (setTitle("Test Frame " + counter++);)。最后,我們在 main 方法中顯示了這窗口類的一個實例,運行得到下圖所示的結果:

Java 圖形用戶界面設計(圖二)
  這個程序的運行結果就是一個什么東西都沒有加的框架,也就是一個空窗口。那么,你知道顯示一個窗口最主要的幾句代碼嗎?不知道沒關系,我來告訴你,顯示一個窗口只需要做三件事:生成實例(對象) -> 設置大小 -> 顯示,相應的,就是下面的三句代碼:

  JFrame frame = new JFrame("Frame's Title");
  frame.setSize(400, 300);
  frame.show();
  也許你會說:第一句的意思我清楚,第三句的意思我也明白,為什么一定要第二句呢?其實想想也就明白了,叫你畫一個沒法有大小的矩形你能畫出來嗎?不能。同樣,沒有大小的窗口,怎么顯示?所以我們需要用 setSize(int width, int height) 方法為其設置大小。我們還有另一種方法:用 JFrame 的 pack() 方法讓它自己適配一個大小。pack() 在多數時候是令人滿足的,但有時,它也會讓你哭笑不得——多試試就知道了。
  在 JFrame 中,我們使用 addWindowListener 方法加入一個監聽器 WindowListener (addWindowListener(new WindowAdapter() ...) 去監聽發生在 JFrame 上的窗口事件。WindowListener 是一個接口,在 java.awt.event 這個包中,但是上例中好象并沒有使用 WindowListener,而是使用的 WindowsAdapter 吧,這是怎么回事?

  WindowAdapter 是 WindowsListener 接口的一個最簡單的實現,也在包 java.awt.event 中。假如我們直接使用 WindowListener 產生一個匿名類,需要實現它的每一個方法 (一共 7 個)。但 WindowAdapter 作為 WindowListener 最簡單的實現,已經實現了它的每一個方法為空方法 (即只包含空語句,或者說沒有語句的方法)。用 WindowAdapter 就只需要重載可能用到的方法 (上例中只有 2 個) 就行了,而不需要再去實現每一個方法。優點顯而易見——減少代碼量。

  在 JFrame 上發生的窗口事件 (WindowEvent) 包括:

windowActivated(WindowEvent e)窗口得到焦點時觸發windowClosed(WindowEvent e)窗口關閉之后觸發windowClosing(WindowEvent e)窗口關閉時觸發windowDeactivated(WindowEvent e)窗口失去焦點時觸發windowDeiconified(WindowEvent e) windowIconified(WindowEvent e) windowOpened(WindowEvent e)窗口打開之后觸發
  上例重載了其中兩個方法。假如在上例運行產生的窗口和另外一個應用程序窗口之間往返切換 (在 Windows 操作系統中你可以使用 Alt+Tab 進行切換)……試試看,你發現了什么?有沒有現我們的示例窗口標題上的數字一直在增加,這便是在 windowActivated 事件中 setTitle("Test Frame " + counter++); 的功勞。

  而另一個事件處理函數 windowClosing 中的 System.exit(0) 則保證了當窗口被關閉時退出當前的 Java 應用程序。假如不作這樣的處理會怎樣呢?試驗之后你會發現,窗口雖然關閉了,但程序并沒有結束,但此時,除了使用 ^C 強行結束之外,恐怕也沒有其它辦法了。所以,這一點非常重要:假如你想在關閉窗口的時候退出應用程序,需要你自己寫代碼處理 windowClosing 事件。……也不盡然,其實還有另外一個更簡單的辦法,讓 JFrame 自己處理這件事——你只需要如下調用 JFrame 的 setDefaultCloseOperation 即可:

  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  我們可以在 JFrame 對象中添加 AWT 或者 Swing 組件。但是,雖然它有 add 方法,卻不能直接用于添加組件,否則會拋出異?!恍啪驮囋?。造成這個現象的原因只有一個解釋:JFrame 不是一個容器,它只是一個框架。那么,應該怎么添加組件呢?

  JFrame 有一個 Content Pane,窗口是顯示的所有組件都是添加在這個 Content Pane 中。JFrame 提供了兩個方法:getContentPane 和 setContentPane 就是用于獲取和設置其 Content Pane 的。通常我們不需要重新設置 JFrame 的 Content Pane,只需要直接獲取這個 Content Pane 來添加組件等。如:(new JFrame()).getContentPane().add(new Button("test button"));
  三. 按鈕、切換按鈕、復選按鈕和單選按鈕

  按鈕,就是按鈕,不會連按鈕都不知道吧?

  切換按鈕,有兩種狀態的按鈕,即按下狀態和彈起狀態,若稱為選擇狀態或未選擇狀態。

  復選按鈕,又叫復選框,用一個小方框中是否打勾來表示兩種狀態。

  單選按鈕,又叫收音機按鈕,以小圓框打點表示被選中。常成組出現,一組單選按鈕中只有一個能被選中。

  發現什么了嗎?——對了,這一部分是在講各種各樣的按鈕,而且后三種按鈕都有兩種狀態。先看看這些按鈕都長成什么樣:

Java 圖形用戶界面設計(圖三)
  上圖中,從上到下,依次就是按鈕、切換按鈕、復選按鈕和單選按鈕。圖示的窗口,就是下面這個例子的運行結果:

/**
* TestButtons.java
* @author Fancy
*/
import javax.swing.*;
import java.awt.event.*;

public class TestButtons {

 JFrame frame = new JFrame("Test Buttons");
 JButton jButton = new JButton("JButton"); //按鈕
 JToggleButton toggle = new JToggleButton("Toggle Button"); //切換按鈕
 JCheckBox checkBox = new JCheckBox("Check Box"); //復選按鈕
 JRadioButton radio1 = new JRadioButton("Radio Button 1"); //單選按鈕
 JRadioButton radio2 = new JRadioButton("Radio Button 2");
 JRadioButton radio3 = new JRadioButton("Radio Button 3");
 JLabel label = new JLabel("Here is Status, look here."); //不是按鈕,是靜態文本

 public TestButtons() {
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.getContentPane().setLayout(new java.awt.FlowLayout());

  /* 為一般按鈕添加動作監聽器 */
  jButton.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent ae) {
   label.setText("You clicked jButton");
  }
 });

 /* 為切換按鈕添加動作監聽器 */
 toggle.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent ae) {
   JToggleButton toggle = (JToggleButton) ae.getSource();
   if (toggle.isSelected()) {
    label.setText("You selected Toggle Button");
   } else {
    label.setText("You deselected Toggle Button");
   }
  }
 });

 /* 為復選按鈕添加條目監聽器 */
 checkBox.addItemListener(new ItemListener() {
 public void itemStateChanged(ItemEvent e) {
  JCheckBox cb = (JCheckBox) e.getSource();
  label.setText("Selected Check Box is " + cb.isSelected());
 }
});

 /* 用一個按鈕組對象包容一組單選按鈕 */
 ButtonGroup group = new ButtonGroup();
 /* 生成一個新的動作監聽器對象,備用 */
 ActionListener al = new ActionListener() {
 public void actionPerformed(ActionEvent ae) {
  JRadioButton radio = (JRadioButton) ae.getSource();
  if (radio == radio1) {
   label.setText("You selected Radio Button 1");
  } else if (radio == radio2) {
   label.setText("You selected Radio Button 2");
  } else {
   label.setText("You selected Radio Button 3");
  }
 }
};
 /* 為各單選按鈕添加動作監聽器 */
 radio1.addActionListener(al);
 radio2.addActionListener(al);
 radio3.addActionListener(al);
 /* 將單選按鈕添加到按鈕組中 */
 group.add(radio1);
 group.add(radio2);
 group.add(radio3);

 frame.getContentPane().add(jButton);
 frame.getContentPane().add(toggle);
 frame.getContentPane().add(checkBox);
 frame.getContentPane().add(radio1);
 frame.getContentPane().add(radio2);
 frame.getContentPane().add(radio3);
 frame.getContentPane().add(label);

 frame.setSize(200, 250);
}

 public void show() {
  frame.show();
 }

 public static void main(String[] args) {
  TestButtons tb = new TestButtons();
  tb.show();
 }

}

  除一般按鈕外,其余三種按鈕都有兩種狀態,即選擇 (按下) 狀態和未選擇 (彈起) 狀態。那么我們又該如何判定呢?切換按鈕 (JToggleButton) 提供了一個 isSelected() 方法用來判定當前所處的狀態,返回值為真 (true) 時表示它處于選擇狀態,返回值為假 (false) 時表示它處于未選擇狀態。而復選按鈕 (JCheckBox) 和單選按鈕 (JRadioButton) 都是從 JToggleButton 繼續的,所以也具有 isSelected() 方法。如上例中 if (toggle.isSelected()) { ... 等。
  單選按鈕由自身的特點決定了它們必須成組出現,而且一組中只能有一個能被選中。因此我們需要用一個專門的類——ButtonGroup——來治理。添加到 ButtonGroup 的多個單選按鈕中,假如有一個被選擇中,同組中的其它單選按鈕都會自動改變其狀態為未選擇狀態。在 ButtonGroup 中添加按鈕,是使用它的 add 方法,如上例中的 group.add(radio1);。

  既然我們已經將多個單選按鈕添加到一個 ButtonGroup 中了,那么我們是不是可以將一個包含多個單選按鈕的 ButtonGroup 對象添加到 JFrame 的 Content Pane 中,以達到添加其中所有單選按鈕的目的呢?不行!ButtonGroup 不是一個可顯示的組件,它僅用于治理。所以,在往 JFrame 中添加一組 JRadioButton 的時候,需要一個一個的添加 JRadioButton,而不是籠統的添加一個 ButtonGroup。

  上例中還用到了 JLabel,這不是按鈕,而是一個靜態文本組件,主要用于顯示提示文本。要獲得一個 JLabel 對象當前顯示的文本內容,可以使用它的 getText() 方法;反之,要改變一個 JLabel 對象顯示的文本內容,應該使用它的 setText(String text) 方法,如上例中的 label.setText("You selected Toggle Button");。

  其實這兩個方法同樣可以用于 JButton 等類。比如上例中我們使用 new JButton("JButton") 構造了一個按鈕 jButton,假如使用 jButton.getText() 就可以得到字符串 "JButton"。而 jButton.setText("A Button"),則可以改變按鈕上顯示的文字為 "A Button"。這兩句代碼沒有寫出來,你可以自己試試。

  上例中大量使用了動作監聽器 (ActionListener)。ActionListener 只監聽一個事件,這個事件在其相關組件上產生了動作時被觸發,因此叫作動作事件 (ActionEvent)。ActionListener 只有一個方法需要實現,就是 actionPerformed(ActionEvent ae)。按鈕、切換按鈕和單選按鈕被單擊時都會觸發動作事件,引起動作監聽器調用 actionPerformed 方法。因此,假如你想在單擊按鈕之后做什么事,當然應該重載 ActionListener 的 actionPerformed 方法了。各種按鈕都提供了 addActionListener 方法以添加動作監聽器。

  復選框就要非凡一些。雖然它也有 addActionListener 方法,意味著可以使用動作監聽器,但是使用之后你會發現動作監聽器并沒有起到預想的作用。為什么?原來,單擊一個復選按鈕,觸發的不是動作事件,而是條目事件 (ItemEvent) 中的狀態變化 (itemStateChanged) 事件,由條目監聽器 (ItemListener) 監聽,相應需要重載的方法是 ItemListener 的 itemStateChanged 方法。

  上例中我們將一個名為 al 的 ActionListener 添加到了每一個單選按鈕中,如何判定是哪個單選按鈕觸發了事件并被 al 監聽到了呢?我們可以從 ActionEvent 的 getSource() 方法得到觸發事件單選按鈕。由于 getSource() 返回的是一個 Object 引用,雖然這個引用指向的是一個單選按鈕的實例,但我們還是需要將這個引用的類型轉換為 JRadioButton,如上例中的:JRadioButton radio = (JRadioButton) ae.getSource();,只有這樣我們才能調用 JRadioButton 有而 Object 沒有的方法。

  同時,還需要說明的一點是,每個單選按鈕都可以添加一個單獨的 ActionListener 實例,而不一定要添加同一個。同樣的道理,若干毫不相干的、需要添加 ActionListener 的若干組件,也可以添加同一個 ActionListener 實例。要害在于編程者對 actionPerformed 方法的重載。比如下面這段代碼就為一個 JButton 對象和一個 JRadioButton 對象添加了同一個動作監聽器實例:

/**
* Test.java
* @author Fancy
*/



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩经典一区二区三区| 在线视频欧美日韩| 国产精品成人久久久久| 大伊人狠狠躁夜夜躁av一区| 欧美激情va永久在线播放| 亚洲视频欧美视频| 亚洲欧洲一区二区三区久久| 亚洲成人xxx| 亚洲精品色婷婷福利天堂| 国产精品一区久久久| 日韩精品视频在线观看免费| 国内精品久久久久久中文字幕| 91精品国产高清| 亚洲第一区在线观看| 精品久久久久久久久久国产| 亚洲精品中文字幕有码专区| 久久免费国产精品1| 久久久精品视频在线观看| 欧美裸体xxxxx| 欧美成人久久久| 欧美日韩中文字幕在线视频| 欧美激情视频网站| 欧美日韩精品在线视频| 欧美国产日本在线| 国产精品女人网站| 国产一区二区三区18| 国产精品视频专区| 国产精品自产拍在线观看| 美女撒尿一区二区三区| 欧美黑人狂野猛交老妇| 日韩在线高清视频| 在线观看91久久久久久| 97久久精品国产| 久久久久免费视频| 国产精品91久久久| 中文字幕视频在线免费欧美日韩综合在线看| 国产精品亚洲第一区| 91av在线精品| 在线观看国产成人av片| 亚洲一区二区三区成人在线视频精品| 伊是香蕉大人久久| 狠狠躁夜夜躁人人爽超碰91| 久久精品免费播放| 亚洲最大成人免费视频| 久久99久久99精品免观看粉嫩| 国产91精品久久久久久久| 国产精品久久久久久久app| 日本久久久久久久久久久| 色综合久久88| 亚洲www永久成人夜色| 亚洲专区在线视频| 国产成人久久久| 亚洲深夜福利在线| 色婷婷久久一区二区| 成人黄色免费在线观看| 欧美日韩在线免费| 国产999精品久久久影片官网| 国产亚洲精品一区二555| 国产91精品黑色丝袜高跟鞋| 亚洲乱码国产乱码精品精| 青青久久aⅴ北条麻妃| 欧美一级成年大片在线观看| 久久久久久久影视| 国产亚洲精品久久| 亚洲国产精品小视频| 国产精品一二区| 国产+成+人+亚洲欧洲| 狠狠躁夜夜躁人人爽超碰91| 亚洲美女又黄又爽在线观看| 欧美激情图片区| 亚洲aa中文字幕| www亚洲欧美| 日韩综合中文字幕| 亚洲欧美日韩在线高清直播| 久久久久久久激情视频| 精品偷拍一区二区三区在线看| 亚洲一区二区国产| 欧美日韩国产成人在线观看| 日韩成人网免费视频| 2025国产精品视频| 久久国产精品久久久久久久久久| 国产精品国产福利国产秒拍| 久久艳片www.17c.com| 一区二区在线视频| 日韩av电影在线免费播放| 国产精品久久综合av爱欲tv| 精品国产依人香蕉在线精品| 91福利视频在线观看| 91久久精品国产91性色| 欧美亚洲日本黄色| 国产精品一区二区av影院萌芽| 中文欧美在线视频| 日韩在线免费观看视频| 91wwwcom在线观看| 亚洲а∨天堂久久精品9966| 亚洲精品一区二区三区婷婷月| 亚洲伦理中文字幕| 久久影视电视剧免费网站清宫辞电视| 亚洲伊人第一页| 91精品国产高清自在线看超| 国产一区二区日韩| 日韩精品视频中文在线观看| 久久青草精品视频免费观看| 一区二区三区www| 日韩av在线影院| 国产精品美女主播在线观看纯欲| 国产精品九九九| 欧美成人h版在线观看| 91sa在线看| 日本在线精品视频| 欧美一级免费看| 日韩成人在线观看| 亚洲天堂av综合网| 亚洲欧美国产精品久久久久久久| 国产精品久久久久久久久久久久久久| 国产免费观看久久黄| 亲爱的老师9免费观看全集电视剧| 狠狠色噜噜狠狠狠狠97| 欧美极品xxxx| 九九久久精品一区| 韩国视频理论视频久久| 国产精品视频免费在线| 亚洲欧美中文日韩在线| 国产精品久久久久av免费| 啪一啪鲁一鲁2019在线视频| 精品中文字幕在线2019| 亚洲天堂av电影| 国产成人高潮免费观看精品| 国产精品海角社区在线观看| 久久综合久中文字幕青草| 黑人狂躁日本妞一区二区三区| 日韩中文字幕在线免费观看| 精品二区三区线观看| 91人人爽人人爽人人精88v| 久久视频精品在线| 国产精品69精品一区二区三区| 日本久久久a级免费| 成人乱色短篇合集| 亚洲影院在线看| 国产欧美日韩免费| 欧美又大又硬又粗bbbbb| 成人亚洲综合色就1024| 日本乱人伦a精品| 久久久噜噜噜久久久| 伦理中文字幕亚洲| 精品视频—区二区三区免费| 亚洲qvod图片区电影| 这里只有精品丝袜| 91久热免费在线视频| 91日本视频在线| 欧美xxxx做受欧美| 国产精品久久久久久久久久免费| 亚洲高清av在线| 久久成人免费视频| 久久九九热免费视频| 成人黄色片在线| 国产成人精品久久二区二区91| 欧美国产第二页| 国产精品久久久久久中文字| 日本一区二区不卡| 国产精品久久久久久久久久久新郎| 国产精品mp4| 国产一区红桃视频| 精品中文字幕乱|