1. 程式人生 > >第四十九講 GUI(圖形使用者介面)

第四十九講 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中都已經定義好了,直接獲取其物件來用就可以了,我們所要做的事情就是對產生的動作進行處理。

事件監聽機制流程圖

在這裡插入圖片描述
事件監聽機制中所要明確的注意點:

  1. 確定事件源(容器或元件);
  2. 通過事件源物件的addXxxListener方法將監聽器註冊到該事件源上,該方法中接收XxxListener的子類物件,或者XxxListener的子類XxxAdapter的子類物件,一般用匿名內部類來表示。在覆蓋方法的時候,方法的引數一般是XxxEvent型別的變數;
  3. 事件觸發後會把事件打包成物件傳遞給該變數(其中包括事件源物件,通過getSource()或者getComponent()獲取)。

按鈕事件

現在想要使用者點選按鈕有效果,比如列印一句話。

思路:

  1. 確定事件源(按鈕);
  2. 確定監聽器,按鈕新增監聽器,按鈕物件最清楚,到按鈕物件中查詢;
  3. 定義處理方式。
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);
	}

}