第四十九講 GUI(圖形使用者介面)
GUI的簡單概述
Graphical User Interface(圖形使用者介面),用圖形的方式,來顯示計算機操作的介面,這樣更方便更直觀。與之相對應的Command line User Interface (命令列使用者介面),就是常見的Dos命令列操作,需要記憶一些常用的命令,操作不直觀。
Awt和Swing
Awt
概述
Java為GUI提供的物件都存在java.awt和javax.swing兩個包中。java.awt就是Abstract Window ToolKit (抽象視窗工具包),需要呼叫本地系統方法實現功能,它屬於重量級控制元件。
繼承關係圖
所有的可以顯示出來的圖形元素都稱為Component,Component代表了所有的可見的圖形元素,Component裡面有一種比較特殊的圖形元素叫Container,Container(容器)在圖形介面裡面是一種可以容納其它Component元素的一種容器,Container本身也是一種Component,Container裡面也可以容納別的Container。
Container裡面又分為Window和Panel,Window是可以獨立顯示出來的,平時我們看到的各種各樣的應用程式的視窗都可以稱為Window,Window作為一個應用程式視窗可以獨立顯示出來,Panel也可以容納其它的圖形元素,但一般看不見Panel,Panel不能作為應用程式的獨立視窗顯示出來,Panel要想顯示出來就必須得把自己裝入到Window裡面才能顯示出來。Panel應用比較典型的就是Applet(Java的頁面小應用程式),現在基本上已經不用了,AJAX和JAVASCRIPT完全取代了它的應用;Window本身又可以分為Frame和Dialog,Frame就是我們平時看到的一般的視窗,而Dialog則是那些需要使用者進行了某些操作(如點選某個下拉選單的項)才出現的對話方塊,這種對話方塊就是Dialog。
佈局管理器
容器中的元件的排放方式,就是佈局。Awt提供了5種佈局管理器類,它們依次是FlowLayout(流式佈局管理器)、BorderLayout(邊界佈局管理器)、GridLayout(網格佈局管理器)、GridBagLayout(網格包佈局管理器)、CardLayout(卡片佈局管理器),但是最屌的佈局還是座標式佈局。下面分別對它們進行簡單的介紹。
FlowLayout
FlowLayout是Panel類的預設佈局管理器。FlowLayout佈局管理器對元件逐行定位,行內從左到右,一行排滿後換行,它不改變元件的大小,按元件原有尺寸顯示元件,可設定不同的元件間距、行距以及對齊方式。FlowLayout佈局管理器預設的對齊方式是居中。
BorderLayout
BorderLayout是Frame類的預設佈局管理器。BorderLayout將整個容器的佈局劃分成東(EAST)、西(WEST)、南(SOUTH)、北(NORTH)、中(CENTER)五個區域,元件只能被新增到指定的區域。如不指定元件的加入部位,則預設加入到CENTER區。每個區域只能加入一個元件,如加入多個,則先前加入的會被覆蓋。
BorderLayout型佈局管理器尺寸縮放原則:北、南兩個區域在水平方向縮放,東、西兩個區域在垂直方向縮放,中部可以在兩個方向上縮放。
GridLayout
GridLayout型佈局管理器將空間劃分成規則的矩形網格,每個單元格區域大小相等。元件被新增到每個單元格中,先從左到右添滿一行後換行,再從上到下。
GridBagLayout
GridBagLayout型佈局管理器將空間劃分成非規則的矩形網格,每個單元格區域大小不一定相等。
CardLayout
CardLayout型佈局管理器將整個容器的佈局劃分成幾個選項卡,諸如下圖這樣。
Swing
概述
javax.swing是在Awt的基礎上建立的一套圖形介面系統,其中提供了更多的元件,而且完全由Java實現。它增強了移植性,屬於輕量級控制元件。
事件監聽機制
事件監聽機制的組成
事件監聽機制由下面幾項組成:
- 事件源:就是java.awt包或者java.swing包中那些圖形介面元件;
- 事件:每一個事件源都有自己特有的對應事件和共性事件(滑鼠、鍵盤事件等);
- 監聽器:將可以觸發某一個事件的動作(不只一個動作)都封裝到監聽器中;
- 事件處理:引發事件後的處理方式。
注意:事件源、事件、監聽器在Java中都已經定義好了,直接獲取其物件來用就可以了,我們所要做的事情就是對產生的動作進行處理。
事件監聽機制流程圖
事件監聽機制中所要明確的注意點:
- 確定事件源(容器或元件);
- 通過事件源物件的addXxxListener方法將監聽器註冊到該事件源上,該方法中接收XxxListener的子類物件,或者XxxListener的子類XxxAdapter的子類物件,一般用匿名內部類來表示。在覆蓋方法的時候,方法的引數一般是XxxEvent型別的變數;
- 事件觸發後會把事件打包成物件傳遞給該變數(其中包括事件源物件,通過getSource()或者getComponent()獲取)。
按鈕事件
現在想要使用者點選按鈕有效果,比如列印一句話。
思路:
- 確定事件源(按鈕);
- 確定監聽器,按鈕新增監聽器,按鈕物件最清楚,到按鈕物件中查詢;
- 定義處理方式。
package cn.liayun.awt.frame;
import java.awt.Button;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class FrameSimple {
public static void main(String[] args) {
// 1,建立一個窗體,通過Frame
Frame f = new Frame("按鈕事件");
// 2,對窗體進行基本設定
f.setSize(500, 400);
f.setLocation(400, 200);
f.setBackground(Color.blue);// 設定窗體的背景顏色
// blue是Color類裡面的一個靜態常量,可以使用"類名.靜態常量名"來訪問
// 設定佈局
f.setLayout(new FlowLayout());
// 給窗體新增元件
Button but = new Button("my button");
// 將元件新增到窗體中
f.add(but);
/*
* 需求:想要使用者點選按鈕有效果,比如列印一句話
* 思路:
* 1,確定事件源(按鈕);
* 2,確定監聽器,按鈕新增監聽器,按鈕物件最清楚,到按鈕物件中查詢;
* 3,定義處理方式。
*
* 定義的規範:XxxListener,Xxx監聽器,有對應的XxxEvent事件。
*/
//1,在按鈕上新增所需的監聽器
but.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("按鈕被觸發了......" + e);
// System.exit(0);
}
});
// 3,讓窗體顯示
f.setVisible(true);
}
}
窗體事件
現在想要實現點選窗體的✗(關閉),就可以實現窗體的關閉。
package cn.liayun.awt.frame;
import java.awt.Button;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class FrameSimple {
public static void main(String[] args) {
// 1,建立一個窗體,通過Frame
Frame f = new Frame("按鈕事件");
// 2,對窗體進行基本設定
f.setSize(500, 400);
f.setLocation(400, 200);
f.setBackground(Color.blue);// 設定窗體的背景顏色
// blue是Color類裡面的一個靜態常量,可以使用"類名.靜態常量名"來訪問
// 設定佈局
f.setLayout(new FlowLayout());
// 給窗體新增元件
Button but = new Button("my button");
// 將元件新增到窗體中
f.add(but);
/*
* 需求:想要使用者點選按鈕有效果,比如列印一句話
* 思路:
* 1,確定事件源(按鈕);
* 2,確定監聽器,按鈕新增監聽器,按鈕物件最清楚,到按鈕物件中查詢;
* 3,定義處理方式。
*
* 定義的規範:XxxListener,Xxx監聽器,有對應的XxxEvent事件。
*/
//1,在按鈕上新增所需的監聽器
but.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("按鈕被觸發了......" + e);
// System.exit(0);
}
});
/*
* 需求:想要實現點選窗體的X,就可以實現窗體的關閉。
* 思路:
* 1,事件源:窗體;
* 2,監聽器,通過窗體物件去查;
* 3,事件處理
*
* 到底哪些監聽介面有介面卡類?
* 只要監聽介面中的方法在2個以內,都沒有介面卡類。介面卡類的出現只為方便建立監聽器物件。
* 但是一般監聽介面都有介面卡。
*/
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.out.println("window closing");
System.exit(0);
}
@Override
public void windowOpened(WindowEvent e) {
System.out.println("孔雀開屏!window open");
}
});
// 3,讓窗體顯示
f.setVisible(true);
}
}
只要監聽介面中的方法在2個以內,都沒有介面卡類。介面卡類的出現只為方便建立監聽器物件,但是一般監聽介面都有介面卡。
滑鼠事件
演示滑鼠監聽。按鈕作為事件源,滑鼠監聽器註冊到按鈕上。
package cn.liayun.awt.frame;
import java.awt.Button;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class FrameSimple {
public static void main(String[] args) {
// 1,建立一個窗體,通過Frame
Frame f = new Frame("按鈕事件");
// 2,對窗體進行基本設定
f.setSize(500, 400);
f.setLocation(400, 200);
f.setBackground(Color.blue);// 設定窗體的背景顏色
// blue是Color類裡面的一個靜態常量,可以使用"類名.靜態常量名"來訪問
// 設定佈局
f.setLayout(new FlowLayout());
// 給窗體新增元件
Button but = new Button("my button");
// 將元件新增到窗體中
f.add(but);
/*
* 需求:想要使用者點選按鈕有效果,比如列印一句話
* 思路:
* 1,確定事件源(按鈕);
* 2,確定監聽器,按鈕新增監聽器,按鈕物件最清楚,到按鈕物件中查詢;
* 3,定義處理方式。
*
* 定義的規範:XxxListener,Xxx監聽器,有對應的XxxEvent事件。
*/
//1,在按鈕上新增所需的監聽器
but.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("按鈕被觸發了......" + e);
// System.exit(0);
}
});
/*
* 需求:想要實現點選窗體的X,就可以實現窗體的關閉。
* 思路:
* 1,事件源:窗體;
* 2,監聽器,通過窗體物件去查;
* 3,事件處理
*
* 到底哪些監聽介面有介面卡類?
* 只要監聽介面中的方法在2個以內,都沒有介面卡類。介面卡類的出現只為方便建立監聽器物件。
* 但是一般監聽介面都有介面卡。
*/
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.out.println("window closing");
System.exit(0);
}
@Override
public void windowOpened(WindowEvent e) {
System.out.println("孔雀開屏!window open");
}
});
/*
* 演示滑鼠監聽。
*
* 按鈕作為事件源。
* 滑鼠監聽器註冊到按鈕上。
*
* 元件.addXxxListener(new XxxAdapter() {
* public void methodName(XxxEvent e) {}
* });
*/
but.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
/*
* 想要對滑鼠雙擊進行處理。應該找滑鼠事件物件,因為事件物件一產生,內部必然封裝事件源以及事件相關內容。
* 要查MouseEvent物件。
*/
if (e.getClickCount() == 2) {
System.out.println("mouse double click");
}
}
});
// 3,讓窗體顯示
f.setVisible(true);
}
}
此時,不僅給按鈕註冊了一個ActionListener(活動監聽器),還給按鈕註冊了一個MouseListener(滑鼠監聽器)。但要注意,按鈕儘量新增ActionEvent(活動事件),當還有點選事件時,點選事件先執行。
鍵盤事件
文字框中只能輸入數字。輸入0-9之外的字元,提示輸入非法,並且無法輸入。
package cn.liayun.awt.frame;
import java.awt.Button;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class FrameSimple {
public static void main(String[] args) {
// 1,建立一個窗體,通過Frame
Frame f = new Frame("按鈕事件");
// 2,對窗體進行基本設定
f.setSize(500, 400);
f.setLocation(400, 200);
f.setBackground(Color.blue);// 設定窗體的背景顏色
// blue是Color類裡面的一個靜態常量,可以使用"類名.靜態常量名"來訪問
// 設定佈局
f.setLayout(new FlowLayout());
// 給窗體新增元件
Button but = new Button("my button");
//加入一個文字框元件
TextField tf = new TextField(40);
// 將元件新增到窗體中
f.add(but);
f.add(tf);
/*
* 需求:想要使用者點選按鈕有效果,比如列印一句話
* 思路:
* 1,確定事件源(按鈕);
* 2,確定監聽器,按鈕新增監聽器,按鈕物件最清楚,到按鈕物件中查詢;
* 3,定義處理方式。
*
* 定義的規範:XxxListener,Xxx監聽器,有對應的XxxEvent事件。
*/
//1,在按鈕上新增所需的監聽器
but.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("按鈕被觸發了......" + e);
// System.exit(0);
}
});
/*
* 需求:想要實現點選窗體的X,就可以實現窗體的關閉。
* 思路:
* 1,事件源:窗體;
* 2,監聽器,通過窗體物件去查;
* 3,事件處理
*
* 到底哪些監聽介面有介面卡類?
* 只要監聽介面中的方法在2個以內,都沒有介面卡類。介面卡類的出現只為方便建立監聽器物件。
* 但是一般監聽介面都有介面卡。
*/
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.out.println("window closing");
System.exit(0);
}
@Override
public void windowOpened(WindowEvent e) {
System.out.println("孔雀開屏!window open");
}
});
/*
* 演示滑鼠監聽。
*
* 按鈕作為事件源。
* 滑鼠監聽器註冊到按鈕上。
*
* 元件.addXxxListener(new XxxAdapter() {
* public void methodName(XxxEvent e) {}
* });
*/
but.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
/*
* 想要對滑鼠雙擊進行處理。應該找滑鼠事件物件,因為事件物件一產生,內部必然封裝事件源以及事件相關內容。
* 要查MouseEvent物件。
*/
if (e.getClickCount() == 2) {
System.out.println("mouse double click");
}
}
});
/*
* 需求:文字框中只能輸入數字。
* 事件源:文字框。
* 文字框註冊鍵盤監聽。
* 事件處理。
*/
tf.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
//1,如何獲取錄入的內容?通過鍵盤事件獲取。
// char key = e.getKeyChar();
// int code = e.getKeyCode();
// System.out.println(code + "..." + KeyEvent.getKeyText(code));
int code = e.getKeyCode();
if (!(code >= KeyEvent.VK_0 && code <= KeyEvent.VK_9)) {
System.out.println("必須是0-9之間的數字");
e.consume();//直接取消預設處理方式
}
//組合鍵的應用
// if (e.isControlDown() && e.getKeyCode() == KeyEvent.VK_ENTER) {
// System.out.println("ctrl + enter run");
// }
}
});
// 3,讓窗體顯示
f.setVisible(true);
}
}