GUI(用戶圖形界面)

一、GUI概述

​ GUI全稱是Graphiacl User Interface,即圖形用戶界面。戶名思議,就是應用程序提供給用戶操作的圖形界面,包括窗口、菜單、按鈕、工具欄和其他各種圖形界面元素。目前,圖形用戶界面已經成爲一種趨勢,幾乎所有的程序設計語言都提供了GUI設計功能。Java中針對GUI設計提供了豐富的類庫,這些類分別位於java.awt和javax.swing包中,簡稱AWT和Swing。其中,AWT是SUN公司最早推出的一套API,它需要利用本地操作系統所提供的圖形庫,屬於重量級組件,不跨平臺,它的組件種類有限,可以提供基本的GUI設計工具,卻無法實現目前GUI設計所需的功能。隨後,SUN公司對AWT進行改進,提供了Swing組件,Swing組件有純java語言編寫,屬於輕量級組件,可跨平臺,Swing不僅實現了AWT中的所有功能,而且還提供了更加豐富的組件和功能,足以滿足GUI設計的一切需求。

二、AWT概述

​ AWT是用於創建圖形用戶界面的一個工具包,它提供了一系列用於實現圖形界面的組件,如窗口、按鈕、文本框、對話框等。在JDK中針對每個組件都提供了對應的Java類,這些類都位於java.awt包中。

​ AWT中組件分爲兩大類,這兩大類基類分貝時Component和Menu Component。其中,Menu Component是所有與菜單相關組件的父類。Component則是除菜單外其他AWT組件的父類,它表示一個能以圖形化方式顯示出來,並可與用戶交互的對象。

​ Compoment類通常被稱爲組件,根據Component的不同作用,可將其分爲基本組件類和容器類。基本組件是諸如按鈕、文本框之類的圖形界面元素,而容器類則是通過Component的子類Container實例化的對象。Container類表示容器,是一種特殊的組件,可以用來容納其他組件。Container容器又分爲兩種類型,分別是Window和Panel

1.Window

Window類是不依賴其他容器而獨立存在的容器,它有兩個子類,分別是Frame類和Dialog類。Frame類用於創建一個具有標題欄的框架窗口,作爲程序的主界面,Dialog類用於創建一個對話框,實現與用戶的信息交互。

2.Panel

Panel也是一個容器,但是它不能單獨存在,只能存在其他容器(Window或其子類)中,一個Panel對象代表了一個長方形的區域,在這個區域中可以容納其他組件。在程序中通常會使用Panel來實現一些特殊的佈局。

案例1:製作第一個窗體

public class Example01 {
	public static void main(String[] args) {
		//建立新窗體對象
		Frame f = new Frame("我的第一個窗體!");
		//設置窗體的寬度和高度
		f.setSize(400,300);
		//設置窗體在屏幕中所處位置(參數是窗口左上角的座標)
		f.setLocation(300,200);
		//設置窗體可見
		f.setVisible(true);
	}
}

三、佈局管理器

​ 之前提到過,組件不能單獨存在,必須放置於容器當中,而組件在容器中的位置和尺寸是由佈局管理器來決定的,在java.awt包中提供了五種佈局管理器,分別是:FlowLayout(流式佈局管理器)、BorderLayout(邊界佈局管理器)、GridLayout(網絡佈局管理器)、GridBagLayout(網絡包佈局管理器)和CardLayout(卡片佈局管理器)。每個容器在創建時都會使用一種默認的佈局管理器,在程序中可以通過調用同期對象的setLayout()方法設置佈局管理器。

例如把一個Frame窗體的佈局管理器設置爲FlowLayout,代碼如下:

Frame frame = new Frame();
frame.setLayout(new FlowLayout());

1.FlowLayout

流式佈局管理是最簡單的佈局管理,在這種佈局下,容器會將組按照添加順序從左向右放置。當達到容器的邊界時,會自動將組建放到下一行的開始位置。這些組建可以左對齊、居中對齊(默認方式)或右對齊的方式排列。FlowLayout對象有三個構造方法。

方法聲明 功能描述
FlowLayout() 組建默認居中對齊,水平,垂直間距默認爲5個單位
FlowLayout(int align) 指定組建相對於容器的對齊方式、水平、垂直間距默認爲5個單位
FlowLayout(int align,int hgap,int vgap) 指定組建的對齊方式,如水平,垂直間距

表中列出了FlowLayout的三個構造方法,其中,參數align決定組建在每行中相對於容器邊界的對齊方式,可以使用該類中提供的常量作爲參數傳遞給構造方法,其中FlowLayout用於表示左對齊、FlowLayout.RIGHT用於表示右對齊、FlowLayout.CENTER用於表示居中對齊。參數hgap和參數vgap分別設定組件之間的水平和垂直間隙,可以填入一個任意數值。

例:

import java.awt.Button;
import java.awt.FlowLayout;
import java.awt.Frame;

public class example02 {
	public static void main(String[] args) {
		//創建一個FlowLayout的窗體
		Frame f = new Frame("FlowLayout");
		//設置窗體中的佈局管理器FlowLayout,所有組件左對齊,水平間距爲20,垂直間距爲30
		f.setLayout(new FlowLayout(FlowLayout.LEFT,20,30));
		//設置窗體大小
		f.setSize(220,300);
		//設置窗體的位置(左上角)
		f.setLocation(300,200);
		//把按鈕添加到f對應的窗口中
		f.add(new Button("第一個按鈕"));
		f.add(new Button("第二個按鈕"));
		f.add(new Button("第三個按鈕"));
		f.add(new Button("第四個按鈕"));
		f.add(new Button("第五個按鈕"));
		f.add(new Button("第六個按鈕"));
		//設置窗體可見
		f.setVisible(true);
	}
}

2.BorderLayout

​ 邊界佈局管理器是一種較爲複雜的佈局方式,它將容器劃分爲五個區域,分別是東(EAST)、南(SOUTH)、西(WEST)、北(NORTH)、中(CENTER)。組件可以被放置在這五個區域中的任意一個。

​ 邊界佈局管理器將容器劃分爲五個區域,其中箭頭是指改變容器大小時,各個區域需要改變的方向。也就是說,在改變容器是NORTH和SOUTH區域高度不變長度調整,WEST和EAST區域寬度不變高度調整增,CENTER會相應進行調整。

​ 當向邊界佈局管理器中添加組件時,需要使用add(Component comp,Object constrains)方法。其中參數comp表示要添加的組件,constrains指定將組件添加到佈局中的方式和對象,它是一個Object類型,在傳參時可以使用BorderLayout提供的五個常量。

例:

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Frame;

public class example03 {

	public static void main(String[] args) {
		//創建一個名爲BorderLayout對的窗體
		Frame f = new Frame("BorderLayout");
		f.setLayout(new BorderLayout());//設置窗體中的佈局管理器BorderLayout
		f.setSize(300,300);//設置大小
		f.setLocation(300,200);
		f.setVisible(true);
		//下面代碼是創建五個按鈕,分別用於填充BorderLayout的五個區域
		Button but1 = new Button("EAST");
		Button but2 = new Button("SOUTH");
		Button but3 = new Button("WEST");
		Button but4 = new Button("NORTH");
		Button but5 = new Button("CENTER");
		//將創建好的按鈕添加到窗體中,並且設置按鈕所在的區域
		f.add(but1,BorderLayout.EAST);
		f.add(but2,BorderLayout.SOUTH);
		f.add(but3,BorderLayout.WEST);
		f.add(but4,BorderLayout.NORTH);
		f.add(but5,BorderLayout.CENTER);
	}
}

3.GridLayout

​ 網格佈局管理器使用縱橫線將容器分成n行m列相等的網格,每個網格中放置一個組件。添加到容器中的組件首先放置在第一行第一列的網格中,然後在第1行的網格中從左向右一次放置其他組件,行滿後,繼續在下一行中從左到右放置組件。與FlowLayout不同的是,放置在GridLayout佈局管理器中的組件將自動佔據整個網格區域。

​ 構造方法:

方法聲明 功能描述
GridLayout() 默認只有一行,每個組件佔一列
GridLayout(int rows,int cols) 指定容器的行數和列數
GridLayout(int rows,int cols,int,hgap,int xgap) 指定容器的行數和列數以及組件之間的水平、垂直間距

水平間隙指的是網格之間的水平距離,垂直間隙同理

import java.awt.Button;
import java.awt.Frame;
import java.awt.GridLayout;

public class example04 {

	public static void main(String[] args) {
		// 創建一個名爲GridLayout的窗體
		Frame f = new Frame("GridLayout");
		f.setLayout(new GridLayout(3,3));//設置該窗體爲3*3的網格
		f.setSize(300,300);
		f.setLocation(200,300);
		//循環添加9個按鈕到GridLayout中
		for(int i=1;i<=9;i++) {
			Button btn = new Button("btn"+i);
			f.add(btn);//向窗體中添加按鈕
		}
		f.setVisible(true);
	}

}

4.GridBagLayout

網格包佈局管理器是最靈活、最複雜的佈局管理器。與GridLayout佈局管理器類似,不同的是,它允許網格中的組件大小各不相同,而且允許一個組件跨越一個或多個網絡。

使用GridBagLayout佈局管理器的步驟如下:

  • 創建GridBagLayout佈局管理器,並使用容器採用該佈局管理器
  • 創建GridBagLayout對象(佈局約束條件),並設置該對象的相關屬性
  • 調用GridBagLayout對象的setConstrains()方法建立GridBagConstrains對象和受控組件之間的並聯
  • 向容器中添加組件

GridBagConstraints對象可以重複使用,只需要改變它的屬性即可。如果要向容器中添加多個組件,則重複(2)、(3)、(4)步驟。

import java.awt.Button;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

//網格包佈局管理器
class Layout extends Frame{
	public Layout(String title) {
		GridBagLayout layout = new GridBagLayout();
		GridBagConstraints c = new GridBagConstraints();//約束對象
		this.setLayout(layout);//設置佈局管理器
		c.fill = GridBagConstraints.BOTH; //設置組件橫向縱向可以拉伸
		c.weightx = 1;//設置橫向權重爲1
		c.weighty = 1;//設置縱向權重爲1
		//增加組件
		this.addComponent("btn1",layout,c);
		this.addComponent("btn2",layout,c);
		this.addComponent("btn3",layout,c);
		c.gridwidth = GridBagConstraints.REMAINDER;//添加的組件是本行的最後一個組件
		this.addComponent("btn4",layout,c);
		c.weightx = 0;//設置縱向權重爲0
		c.weighty = 0;//設置縱向權重爲0
		this.addComponent("btn5",layout,c);
		c.gridwidth = 1;//設置組件跨一個網格(默認值)
		this.addComponent("btn6",layout,c);
		c.gridwidth = GridBagConstraints.REMAINDER;//添加的組件是本行的最後一個組件
		this.addComponent("btn7",layout,c);
		c.gridwidth = 1;//設置組件跨2個網格
		c.gridheight = 2;////設置組件跨一個網格(默認值)
		c.weightx = 2;//設置縱向權重爲2
		c.weighty = 2;//設置縱向權重爲2
		this.addComponent("btn8",layout,c);
		c.gridwidth = GridBagConstraints.REMAINDER;//添加的組件是本行的最後一個組件
		c.gridheight = 1;//設置組件跨1個網格
		this.addComponent("btn9",layout,c);
		this.addComponent("btn10",layout,c);

		this.setTitle(title);//設置窗體的標題
		this.pack();//設置自動窗體大小
		this.setVisible(true);
	}
	//添加組件的方法,通過指定的約束,將組件添加到佈局管理器中
	public void addComponent(String name,GridBagLayout layout,GridBagConstraints c) {
		Button bt = new Button(name);//創建一個名爲name的按鈕
		layout.setConstraints(bt, c);//設置約束對象和按鈕的關聯
		this.add(bt);
	}
}
public class example05 {
	public static void main(String[] args) {
		new Layout("GridBagLayout");
	}
}

從上面的步驟可以看出,使用GridBagLayout佈局管理器關鍵在於GridBagConstraints對象,它纔是控制容器中每個組件佈局的核心類,在GridBagConstraints類中有很多表示約束的屬性.

  • GridBagConstraints.gridwidthGridBagConstraints.gridheight

    指定組件顯示區域中一行中的單元格數(對於gridwidth )或列(對於gridheight )。 默認值爲1.使用GridBagConstraints.REMAINDER指定組件的顯示區域將從gridx到行中的最後一個單元格(對於gridwidth ),或從gridy到列中的最後一個單元格(對於gridheight )。 使用GridBagConstraints.RELATIVE來指定組件的顯示區域將從gridx到其行中最後一個單元格的下一個(對於gridwidth或從其列中的最後一個單元格的gridygridheight )。

  • GridBagConstraints.fill

    當組件的顯示區域大於組件的請求大小時使用,以確定是否(以及如何)調整組件的大小。 可能的值爲GridBagConstraints.NONE (默認值), GridBagConstraints.HORIZONTAL (使組件足夠寬,可以水平填充其顯示區域,但不要更改其高度), GridBagConstraints.VERTICAL (使組件足夠高以垂直填充其顯示區域,但不要更改其寬度)和GridBagConstraints.BOTH (使組件完全填充其顯示區域)。

  • GridBagConstraints.weightx、GridBagConstraints.weighty

    用於確定如何分配空間,這對於指定調整大小的行爲很重要。 除非您指定一行中至少一個組件( weightx )和列( weighty )的權重,否則所有組件都將集中在其容器的中心。 這是因爲當重量爲零(默認值)時, GridBagLayout對象在其單元格格柵和容器邊緣之間放置任何額外的空格。

5.CardLayout

​ 在操作程序時,經常會遇到通過選項卡按鈕來切換程序中的界面,這些界面就相當於一張張卡片,而管理這些卡片的佈局管理器就是卡片佈局管理器。卡片佈局管理器將界面看做是一系列卡片,在任何時候只有其中一張卡片是可見的,這張卡片佔據容器的整個區域。

​ 在CardLayout不倦利器中經常會用到下面幾個方法:

方法聲明 功能需求
void first(Container parent) 顯示parent容器第一張卡片
void last(Container parent) 顯示parent容器的最後一張卡片
void previous(Container parent) 顯示parent容器的前一張卡片
void next(Container parent) 顯示parent容器的下一張卡片
void show(Container parent,String name) 顯示parent容器中名稱爲name的組件,如果不存在,則不會發生任何操作
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.CardLayout;
import java.awt.Frame;
import java.awt.Label;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

class cardLayout extends Frame implements ActionListener{
	CardLayout cardlayout = new CardLayout();//定義卡片佈局管理器
	Panel cardPanel = new Panel();//定義面板,放置卡片內容
	Panel controlPanel = new Panel();//定義面板,放置按鈕
	Button preButton;//聲明切換到上一張卡片的按鈕
	Button nextButton;//聲明切換到下一張卡片的按鈕
	public cardLayout() {
		this.setSize(300,200);//設置窗體大小
		cardPanel.setLayout(cardlayout);//設置佈局爲卡片佈局管理器
		//在cardPanel中添加三個文本標籤
		cardPanel.add(new Label("第一個界面",Label.CENTER));
		cardPanel.add(new Label("第二個界面",Label.CENTER));
		cardPanel.add(new Label("第三個界面",Label.CENTER));
		//創建兩個按鈕
		nextButton = new Button("下一張卡片");
		preButton = new Button("上一張卡片");
		//將按鈕添加到controlButton面板中
		controlPanel.add(preButton);
		controlPanel.add(nextButton);
		//把面板添加到窗體中顯示
		this.add(cardPanel,BorderLayout.CENTER);
		this.add(controlPanel, BorderLayout.SOUTH);
		this.setVisible(true);//設置窗體顯示
		
		//爲按鈕添加監聽事件
		nextButton.addActionListener(this);
		preButton.addActionListener(this);
		
		//爲窗口添加關閉事件監聽器
		this.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				cardLayout.this.dispose();
			}
		});
	}
	//實現按鈕的監聽觸發,並對觸發實踐做出相應的處理方式
	@Override
	public void actionPerformed(ActionEvent e) {
		//如果用戶點擊nextButton,執行操作
		if(e.getSource()== nextButton) {
			//切換cardPanel面板當前卡片,向後切換一張
			cardlayout.next(cardPanel);
		}
		if(e.getSource()== preButton) {
			cardlayout.previous(cardPanel);
		}
	}
	
}
public class example06 {
	public static void main(String[] args) {
		cardLayout layout = new cardLayout();
	}
}

6.不使用佈局管理器

​ 當一個容器被創建後,它們都會有一個默認的佈局管理器。Window、Frame和Dialog的默認佈局管理器是BorderLayout,Panel的默認佈局管理器是FlowLayout。如果不希望通過佈局管理器來對容器進行佈局,也可以調用容器的setLayout(null)方法,將佈局管理器取消。在這種情況下,程序必須調用容器中每個組件的setSize和setLocation方法或者是setBounds方法(這個方法接受四個參數,分別是左上角的x、y座標和組件的長、寬)來爲這些組件在容器中定位。

import java.awt.Button;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class example07{
	public static void main(String[] args) {
		Frame f = new Frame("不使用佈局管理器");
		//取消當前窗體的不管理器
		f.setLayout(null);
		f.setSize(300,150);
		Button bt1 = new Button("press");
		Button bt2 = new Button("pop");
		//設置按鈕顯示的位置與大小
		bt1.setBounds(40, 60, 100, 30);
		bt2.setBounds(140, 90, 100, 30);
		f.add(bt1);
		f.add(bt2);
		f.setVisible(true);
        //添加了關閉窗口監聽事件
		f.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				f.dispose();
			}
		});
	}
}

四、AWT事件處理

1.事件處理機制

​ 如果不設置任何東西,單機窗口右上角的關閉按鈕會發現窗口無法關閉,這說明該按鈕的單機功能沒有實現。按理說Frame對象應該實現這個按鈕的功能,之所以沒有實現,是因爲Frame的設計者無法確定用戶關閉Frame窗口的方式,例如:是直接關閉窗口還是需要彈出對話框詢問用戶是否關閉。如果想要關閉窗口,就需要通過實踐處理機制對窗口進行監聽。

​ 實踐處理機制專門用於響應用戶的操作。比如,想要響應用戶的單機鼠標、按下鍵盤的操作,就需要使用AWT的時間處理機制。在學習如何使用awt事件處理機制之前,首先向讀者介紹幾個比較重要的概念,具體概念如下:

  • 事件對象(Event):封裝GUI組件上發生的特定時間(通常就是用戶的一次操作)
  • 事件源(組件):時間發生的場所,通常就是產生事件的組件
  • 監聽器(Listener):負責監聽事件源上發生的事件,並對各種時間做出相應處理的對象(對象中包含事件處理器)
  • 事件處理器,監聽器對象接受的事件對象進行相應處理的方法

​ 上面提到的事件對象、事件源、監聽器、事件處理器在整個事件處理機制中都起着非常重要的作用,他們彼此之間有着非常緊密的聯繫。

​ 程序中,如果想實現事件的監聽機制,首先需要定義一個實現了事件監聽器接口的類,例如Window類型的窗口需要實現WindowsListener。接着通過addWindowLinstener()方法爲時間源註冊時間監聽器的對象,當事件源上發生事件時,便會觸發時間監聽對象,由時間監聽器調用相應的方法來處理相應的事件。

import java.awt.Frame;
import java.awt.Window;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

public class example08 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//創建新窗體
		Frame f = new Frame("我的窗體");
		f.setSize(400,300);//設置窗體尺寸大小
		f.setLocation(300,200);//設置窗口的位置
		f.setVisible(true);//設置窗口的顯示
		//爲窗口組件註冊監聽器
		f.addWindowListener(new MyWindowListener());
	}
}

//創建MyWindowLinstener類實現WindowListener接口
class MyWindowListener implements WindowListener{

	@Override
	public void windowOpened(WindowEvent e) {}

	@Override
	public void windowClosing(WindowEvent e) {
		// 監聽器監聽事件對象作出處理
		Window window = e.getWindow();
		window.setVisible(false);
		//窗口的釋放
		window.dispose();
	}

	@Override
	public void windowClosed(WindowEvent e) {}

	@Override
	public void windowIconified(WindowEvent e) {}

	@Override
	public void windowDeiconified(WindowEvent e) {}

	@Override
	public void windowActivated(WindowEvent e) {}

	@Override
	public void windowDeactivated(WindowEvent e) {}
}

2.事件適配器

​ MyWindowLinstener類實現WindowLinstener接口後,需要實現接口中定義的七個方法,然而在程序中只需要windowClosing()一個方法,其他六個方法都是空實現,沒有發揮任何作用,這樣代碼的編寫明顯是多餘的但是右必需的工作。正對這樣的問題,JDK提供了一些適配器,他們是監聽接口的默認實現類,這些實現類中實現了接口的所有方法,但方法中沒有任何代碼,程序可以通過繼承適配器來達到實現監聽接口的目的。

import java.awt.Frame;
import java.awt.Window;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class example09 {
	public static void main(String[] args) {
		Frame f = new Frame("繼承適配器");
		f.setSize(400,300);
		f.setLocation(200,300);
		f.setVisible(true);
		//爲窗口組件註冊監聽器
		f.addWindowListener(new MyWindowListener02());
	}
}

class MyWindowListener02 extends WindowAdapter{
	@Override
	public void windowClosing(WindowEvent e) {
		Window window = (Window) e.getComponent();
		window.dispose();
	}
}

3.匿名內部類實現事件處理

​ 在實際開發中,爲了代碼的簡潔,經常通過匿名內部類來創建監聽器對象,正對所發生的事件進行處理。

import java.awt.Button;
import java.awt.Frame;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

/**
 * 用匿名內部類實現事件處理
 */
public class example10 {
	public static void main(String[] args) {
		Frame f = new Frame("匿名內部類實現事件處理");
		f.setSize(400,300);
		f.setLocation(300,200);
		f.setVisible(true);
		Button bt1 = new Button("EXIT");
		f.add(bt1);
		//用匿名內部類的方法實現爲按鈕註冊監聽器
		bt1.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				System.exit(0);
			}
		});
	}
}

五、常用事件分類

1.窗口事件

​ 大部分GUI應用程序都需要使用Window窗體對象作爲最外層的容器,可以說窗體對象是所有GUI應用程序的基礎,應用程序中通常都是將其他組件直接或者間接置於窗體中。

​ 當對窗體進行操作時,比如窗體的打開、關閉、激活、停用等,這些馮作都屬於窗體時間,JDK提供了一個類WindowEvent用於表示這些窗體事件。在應用程序中,當對窗體事件進行處理時,首先需要定義一個實現了WindowListener接口類作爲窗體監聽器,然後通過addWindowListener()方法將窗體對象與窗體監聽器綁定。

import java.awt.Frame;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

public class example11 {
/**
 * 窗口事件
 */
	public static void main(String[] args) {
		Frame f = new Frame("windowEvent");
		f.setSize(400,300);
		f.setLocation(300,200);
		f.setVisible(true);
		//使用內部類創建WindowListener對象,監聽窗體事件
		f.addWindowListener(new WindowListener() {
			@Override
			public void windowOpened(WindowEvent e) {
				System.out.println("WindowOpened --- 窗體打開激活事件");
			}

			@Override
			public void windowClosing(WindowEvent e) {
				System.out.println("windowClosing --- 窗體正在執行關閉時的操作");
			}

			@Override
			public void windowClosed(WindowEvent e) {
				System.out.println("windowClosed --- 窗口關閉事件");
				
			}

			@Override
			public void windowIconified(WindowEvent e) {
				System.out.println("windowIconified --- 窗體圖標化事件(最小化)");
			}

			@Override
			public void windowDeiconified(WindowEvent e) {
				System.out.println("windowDeiconified --- 窗體取消圖標化事件");
			}

			@Override
			public void windowActivated(WindowEvent e) {
				System.out.println("windowActivated --- 窗體激活事件");
			}

			@Override
			public void windowDeactivated(WindowEvent e) {
				System.out.println("windowDeactivated--窗體停用事件");
			}
		});
	}
}

2.鼠標事件

​ 在圖形用戶界面中,用戶經常會使用鼠標來進行選擇、切換界面操作,這些操作被定義爲鼠標事件,其中包括鼠標按下、鼠標鬆開、鼠標單擊等。JDK中提供了一個MouseEvent類用於表示鼠標事件,幾乎所有的組件都可以產生鼠標事件。處理鼠標事件時,首先需要通過實現MouseListener接口定義監聽器(也可以通過繼承適配器MouseAdapter類來實現),然後調用addMouseListener()方法將監聽器綁定到之間源對象。

import java.awt.Button;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class example12 {
	public static void main(String[] args) {
		Frame f = new Frame("MouseEvent");
		f.setLayout(new FlowLayout());
		f.setSize(300,200);
		f.setLocation(300,200);
		f.setVisible(true);
		Button btn = new Button("Button");
		f.add(btn);//將按鈕添加到窗體
		//爲按鈕添加鼠標事件監聽器
		btn.addMouseListener(new MouseListener() {
			@Override
			public void mouseClicked(MouseEvent e) {
				System.out.println("mouseClicked---鼠標點擊事件");
			}

			@Override
			public void mousePressed(MouseEvent e) {
				System.out.println("mousePressed---鼠標按下事件");
			}

			@Override
			public void mouseReleased(MouseEvent e) {
				System.out.println("mouseReleased---鼠標放開事件");
			}

			@Override
			public void mouseEntered(MouseEvent e) {
				System.out.println("mouseEntered---鼠標進入按鈕區域的事件");
			}

			@Override
			public void mouseExited(MouseEvent e) {
				System.out.println("mouseExited---鼠標移出按鈕區域的事件");
			}
		});
	}
}

3.鍵盤事件

​ 鍵盤操作也是最常用的用戶交互方式,例如鍵盤按下、釋放等,這些操作被定義爲鍵盤事件。JDK中提供了一個KeyEvent類表示鍵盤事件,處理KeyEvent事件的監聽器對象需要實現KeyListener接口或者KeyAdapter類。

import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.TextField;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class example13 {
/**
 * 鍵盤監聽
 */
	public static void main(String[] args) {
		Frame f = new Frame("KeyEvent");
		f.setLayout(new FlowLayout());
		f.setSize(400,300);
		f.setLocation(200,300);
		f.setVisible(true);
		
		TextField tf = new TextField(30);//創建一個文本框對象
		f.add(tf);
		
		tf.addKeyListener(new KeyAdapter() {

			@Override
			public void keyPressed(KeyEvent e) {
				int keyCode = e.getKeyCode();//返回所按按鍵對應的整數值
				//返回按鍵的字符串描述
				String s = KeyEvent.getKeyText(keyCode);
				//輸出相關信息
				System.out.println("鍵盤輸入的內容爲"+s+",");
				System.out.println("對應的keyCode值爲:"+keyCode+",");
			}
		});
		//用匿名內部類實現窗口關閉
		f.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
	}
}

4.動作事件

​ 動作事件與前面三種事件有所不同,它不代表某個具體動作,只是表示一個動作發生了。例如,在關閉一個文件時,可以通過鍵盤關閉,也可以通過鼠標關閉。在這裏不需要關心使用哪種方式對文件進行關閉,只要是對關閉按鈕進行操作,即出發了動作事件。

​ 在java中,董總事件用ActionEvent類表示,處理ActionEvent事件的監聽器對象需要實現ActionListener接口。監聽器對象在監聽動作時,不會像鼠標事件一樣處理鼠標的移動和單機的細節,而是去處理類似於“按鈕按下”這樣有意義的事件。

5.AWT繪圖

​ 很多GUI程序都需要在組件上繪製圖形,比如說實現一個五子棋的小遊戲,就需要在組件上繪製棋盤和妻子。在java.awt包中專門提供了一個Graphics類,它相當於一個抽象的畫筆,其中提供了各種繪製圖形的方法,使用Graphics類的方法就可以完成在組件上繪製圖形。表中列出了Graphics類常用的方法。

方法聲明 方法描述
void setColor(Color c) 將此圖形上下文的當前顏色設置爲指定的顏色。
void setFont(Font font) 將此圖形上下文的字體設置爲指定的字體。
void drawLine(int x1, int y1, int x2, int y2) 在該圖形上下文的座標系中的點 (x1, y1)(x2, y2)之間繪製一行,使用當前顏色。
void drawRect(int x, int y, int width, int height) 繪製指定矩形的輪廓。
void drawOval(int x, int y, int width, int height) 繪製橢圓形輪廓。
void fillRect(int x, int y, int width, int height) 填寫指定的矩形
void fillOval(int x, int y, int width, int height) 用當前顏色填充由指定矩形界定的橢圓。
void drawString(String str,int x,int y) 使用該圖形上下文的當前字體和顏色繪製由指定字符串給出的文本。

例:利用awt寫一個驗證碼生成器

import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Panel;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Random;

public class example14 {
/**
 * AWT繪圖
 */
	public static void main(String[] args) {
		Frame frame = new Frame("驗證碼");
		Panel panel = new MyPanel();
		frame.add(panel);
		frame.setSize(200,100);
		//將frame窗口居中
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);

		//利用匿名內部類實現關閉操作
		frame.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
	}
}

class MyPanel extends Panel {
	@Override
	public void paint(Graphics g) {
		int width = 160;//定義驗證碼所對應的圖片寬度
		int height = 40;//定義驗證碼圖片的高度
		g.setColor(Color.LIGHT_GRAY);//設置畫筆顏色
		//繪製驗證碼的背景
		g.fillRect(0, 0, width-1, height-1);
		//設置畫筆顏色
		g.setColor(Color.BLACK);
		//設置邊框
		g.drawRect(0, 0, width, height);
		//繪製干擾點
		Random r = new Random();
		for(int i=0;i<100;i++) {
			int x = r.nextInt(width) -2;
			int y = r.nextInt(height)-2;
			g.drawOval(x, y, 2, 2);
		}
		//設置驗證碼字體
		g.setFont(new Font("黑體",Font.BOLD,30));
		//設置驗證碼文字顏色
		g.setColor(Color.red);
		//產生隨機驗證碼操作
		StringBuffer sb = new StringBuffer();
		char[] chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
		for (int i = 0; i < 4; i++) {
			int pos = r.nextInt(chars.length);
			char c = chars[pos];
			sb.append(c+" ");
		}
		//繪製驗證碼字符串文字
		g.drawString(sb.toString(), 20, 30);
	}
}

六、Swing

​ 一開始提到JDK中針對GUI提供的API包括AWT和Swing。前面的都是正對AWT的瞭解,接下來針對swing組件進行講解。相對於awt來說,swing包提供了更加豐富、邊界、強大的GUI組件,而且這些組件都是java語言編寫而成的,因此,swing組件不依賴於本地平臺,可以真正做到跨平臺運行。通常來講,把依賴與本地平臺的awt稱作重量級組件,而把不依賴本地平臺的swing組件成爲輕量級組件。

​ 學習swing組件的過程和學習awt差不多,大部分swing組件都是JComponent類的直接或間接子類,而JComponent類是AWT中java.awt.Container的子類,說明swing組件和awt組件在繼承樹上形成了一定的關係。

1.JFrame

​ 在Swing組件中,最常見的就是一個JFrame,它和Frame一樣是一個獨立存在的頂級窗口,不能放置在其他容器中,JFrame支持通用窗口的索引基本功能,例如窗口的最小化,設定窗口大小等。

import java.awt.FlowLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
/**
 * JFrame的使用
 */
public class example01 extends JFrame{
	public example01() {
		this.setTitle("JFrameTest");
		this.setSize(250, 300);
		//設置居中顯示
		this.setLocationRelativeTo(null);
		//定義一個按鈕
		JButton bt = new JButton("按鈕");
		//設置流式佈局管理器
		this.setLayout(new FlowLayout());
		//添加按鈕
		this.add(bt);
		
		//設置點擊關閉按鈕時,默認操作
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setVisible(true);
	}
	
	public static void main(String[] args) {
		new example01();
	}
}

2.JDialog

​ JDialog是另外一個頂級窗口,它和Dialog一樣都表示對話框。JDialog對話框可分爲兩種:靜態對話框和非靜態對話框。所謂模式對話框是指用戶需要等到處理完對話框後才能繼續與其他窗口交互的對話框,而非模式對話框是允許用戶在處理對話框的同時與其他窗口交互的對話框。

​ 對話框是模式或者費模式,可以在創建JDialog對象是爲構造方法傳入參數來設置,也可以在創建JDialog對象後調用它的setModal()方法來進行設置。JDialog常見的構造方法如表所示。

方法聲明 功能描述
JDialog(Frame owner) 創建一個無模式對話框,其中指定的是 Frame作爲其所有者,並且是一個空的標題。
JDialog(Frame owner, String title) 使用指定的標題和指定的所有者框架創建無模式對話框
JDialog(Frame owner, boolean modal) 創建一個具有空標題和指定模態的對話框,並以 Frame作爲其所有者。
import java.awt.FlowLayout;
import java.awt.Label;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;

/**
 * JDialog對話框
 */
public class example02 {
	public static void main(String[] args) {
		//建立兩個按鈕
		JButton btn1 = new JButton("模式對話框");
		JButton btn2 = new JButton("非模式對話框");
		JFrame f = new JFrame("JDialogDemo");
		f.setSize(300, 250);
		f.setLocationRelativeTo(null);//設置居中效果
		f.setLayout(new FlowLayout());//設置佈局管理模式
		//添加按鈕
		f.add(btn1);
		f.add(btn2);
		//設置點擊關閉按鈕的默認操作
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.setVisible(true);
		
		//創建JDialog
		final JDialog dialog = new JDialog(f,"Dialog");
		dialog.setSize(220, 150);
		dialog.setLocation(350, 150);//設置對話框顯示位置
		dialog.setLayout(new FlowLayout());//設置對話框的佈局管理器
		JButton btn3 = new JButton("確定");
		dialog.add(btn3);//在對話框中添加按鈕
		final Label label = new Label("標籤");
		dialog.add(label);
		
		//爲“模式對話框”按鈕,添加點擊事件
		btn1.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				//設置對話框的狀態設置爲模式對話框
				dialog.setModal(true);
				//修改標籤的內容
				label.setText("模式對話框,點擊確定按鈕關閉");
				//顯示對話框
				dialog.setVisible(true);
			}
		});
		//爲“非模式對話框”按鈕,添加點擊事件
		btn2.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				//設置對話框的狀態設置爲模式對話框
				dialog.setModal(false);
				//修改標籤的內容
				label.setText("非模式對話框,點擊確定按鈕關閉");
				//顯示對話框
				dialog.setVisible(true);
			}
		});
		//爲對話框中的按鈕添加點擊事件
		btn3.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				dialog.dispose();
			}
		});
	}
}

3.中間容器

​ Swing組件不僅具有JFrame和Dialog這樣的頂級窗口,還提供了一些中間容器,這些容器不能單獨存在,只能放置在頂級窗口中。最常見的中間容器有兩種:JPanel和JScrollPane。

  • JPanel:JPanel和AWT中的Panel組件使用方法一致,它是一個無邊框,不能被移動、方法、縮小或者關閉的面板,它的默認佈局管理器是流佈局。當然也可以使用JPanel帶參數的構造函數JPanel(LayoutManager layout)或者它的setLayout()方法爲其制定佈局管理器。
  • JScrollPane:與JPanel不同的是,JScrollPanel是一個都帶有滾動條的面板容器,而且這個面積只能添加一個組件,如果想在JScrollPane面板中添加多個組件,應該先將組件添加到JPanel中,然後將JPanel添加到JScrollPane中
import java.awt.Button;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;

/**
 * 中間容器添加按鈕
 */
public class example03 extends JFrame{

	public example03() {
		this.setTitle("PanelDemo");
		this.setLocationRelativeTo(null);
		
		//定義一個JPanel面板
		JPanel panel = new JPanel();
		
		//在pannel面板添加四個按鈕
		panel.add(new Button("按鈕1"));
		panel.add(new Button("按鈕2"));
		panel.add(new Button("按鈕3"));
		panel.add(new Button("按鈕4"));
		
		//創建一個滾動面板
		JScrollPane scrollpane = new JScrollPane();
		//設置水平滾動條一直顯示效果	
		scrollpane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		//設置垂直滾動條的顯示效果,需要時顯示
		scrollpane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		//設置panel面板在滾動面板中顯示
		scrollpane.setViewportView(panel);
		
		
		//將面板scrollpane添加到窗體中
		this.add(scrollpane);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setSize(400, 250);
		this.setVisible(true);
	}
	
	public static void main(String[] args) {
		new example03();
	}
}

4.文本組件

​ 文本組件用於接收用戶輸入的信息或向用戶展示信息,其中包括文板框(JTextField)、文本域(JTextArea)等。他們都有一個共同的父類JTextComponent。

import java.awt.BorderLayout;
import java.awt.Label;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

/**
 * 文本組件JTextField與JTextArea
 */
public class example04 extends JFrame{

	public example04() {
		//基本設定
		this.setLayout(new BorderLayout());//設置窗口布局
		this.setTitle("聊天窗口");//設置窗口標題
		this.setLocation(500,300);
		this.setSize(400, 300);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		//上面部分
		final JTextArea chatContent = new JTextArea(12,34);//創建一個文本域
		chatContent.setEditable(false);//設置文本域不可修改
		//創建有一個滾動面板,並把文本域添加到滾動面板中
		JScrollPane showPanel = new JScrollPane(chatContent);
		//添加滾動面板到窗口中
		this.add(showPanel,BorderLayout.CENTER);
		
		//下面部分
		Label label = new Label("聊天信息");//創建一個標籤
		final JTextField inputField = new JTextField(20);
		JButton sendBt = new JButton("發送");//創建按鈕
		JPanel inputPanel = new JPanel();//創建一個面板,用來存儲下面的組件
		//添加組件到下面的面板中
		inputPanel.add(label);
		inputPanel.add(inputField);
		inputPanel.add(sendBt);
		//添加下面的面板到窗口中
		this.add(inputPanel,BorderLayout.SOUTH);//添加下面的面板到窗口中
		//爲按鈕添加事件
		sendBt.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				String content = inputField.getText();//獲取輸入文本框內容
				if(content != null && !content.trim().equals("")) {
					//如果內容不爲空,將輸入的文本信息追加到聊天的從窗口中
					chatContent.append("本人:"+content+"\n");
				}else {
					//如果內容爲空,提示聊天信息不能爲空
					chatContent.append("聊天信息不能爲空\n");
				}
				//將文本框的內容設置爲空
				inputField.setText("");
			}
		});
		this.setVisible(true);
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new example04();
	}
}

5.按鈕組件

​ 在Swing中,常見的按鈕組件有JButton、JCheckBox、JRadioButton等,他們都是抽象類AbstractButton類的直接或間接子類。

1.JCheckBox

​ JCheckBox又稱複選框,它有選中(是)/未選中(否)兩種狀態,如果用戶想接收的輸入只有“是”和“非”,則可以通過複選框來切換狀態。如果複選框有多個,則用戶可以選中其中一個或多個。

方法描述 功能說明
JCheckBox() 創建一個最初未選擇的複選框按鈕,沒有文字,沒有圖標。
JCheckBox(String text) 創建一個最初未選擇的複選框與文本。
JCheckBox(String text, boolean selected) 創建一個帶有文本的複選框,並指定是否最初選擇它。

​ 表中,,列出了用於創建JCheckBox對象三個構造方法。其中,第一個構造方法沒有指定複選框的文本信息以及狀態,如果想設置文本信息,可以通過調用JCheckBox從父類繼承的方法來進行設置。第二個和第三個構造方法都制定了複選框的文本信息,而且第三個構造方法還制定了複選框初始化狀態是否被選中。

import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

/**
 * JCheckBox組件(複選框)
 */
public class example05 extends JFrame{
	public example05() {
		//創建一個標籤,標籤中的文本信息進行居中顯示
		JLabel label =new JLabel("李璽,你好",JLabel.CENTER);
		label.setFont(new Font("宋體",Font.PLAIN,20));//設置標籤文字的字體
		this.add(label);//把標籤添加到窗體中顯示
		this.setSize(300, 300);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		//下面的
		JCheckBox italic = new JCheckBox("italic");//傾斜效果
		JCheckBox bold = new JCheckBox("bold");//粗體效果
		JPanel panel = new JPanel();//創建窗口顯示
		//添加複選框按鈕到面板中
		panel.add(bold);
		panel.add(italic);
		//把面板添加到窗體的下方
		this.add(panel,BorderLayout.SOUTH);
		
		//爲複選框定義ActionListener監聽器
		ActionListener listener = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				int mode = Font.PLAIN;//默認字體樣式
				if(italic.isSelected()) {
					//選中傾斜的複選框
					mode+=Font.ITALIC;
				}
				if(bold.isSelected()) {
					mode+=Font.BOLD;
				}
				//設置當前標籤文字的樣式
				label.setFont(new Font("宋體",mode,20));
			}
		};
		
		//爲兩個複選框添加監聽器
		italic.addActionListener(listener);
		bold.addActionListener(listener);
		this.setVisible(true);//設置窗體顯示
	}
	
	public static void main(String[] args) {
		new example05();
	}
}

2.JRadionButton

​ JRadioButton組件被成爲單選按鈕,與JCheckBox複選框不同的是,單選按鈕只能選一個。就像隨身聽上的播放和快進按鈕,當按下一個,先前按下的按鈕就會自動彈起。對於JRadioButton按鈕來說,當一個按鈕被選中時,先前被選中的按鈕就會自動取消選中。

​ 由於JRadioButton組件本身並不具備這種功能,因此若想實現JRadioButton按鈕之間的互斥,需要使用javax.swing.ButtonGroup類,它是一個不可見的組件,不需要將其增加到容器中顯示,知識在邏輯上表示一個單選按鈕組。將多個JRadioButton按鈕添加到同一個單選按鈕組對象中,就能實現按鈕的單選功能。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;

/**
 * JRadioButton組件的使用
 *
 */
public class example06 extends JFrame{
	public example06() {
		final JPanel pallet = new JPanel();//創建一個調色板
		this.add(pallet,BorderLayout.CENTER);//將調色板添加到窗體的中間位置
		
		ButtonGroup group = new ButtonGroup();//單選按鈕組對象
		JRadioButton btn1 = new JRadioButton("灰");
		JRadioButton btn2 = new JRadioButton("粉");
		JRadioButton btn3 = new JRadioButton("黃");
		//添加按鈕到按鈕組中
		group.add(btn1);
		group.add(btn2);
		group.add(btn3);
		JPanel panel = new JPanel();//創建一個面板
		panel.add(btn1);//按鈕添加到面板中
		panel.add(btn2);
		panel.add(btn3);
		//添加面板到窗體的下方
		this.add(panel,BorderLayout.SOUTH);
		this.setSize(300, 300);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//創建單選按鈕的ActionListener監聽器
		ActionListener listener = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				Color color = null;
				if(btn1.isSelected()) {
					color = Color.GRAY;
				}else if (btn2.isSelected()) {
					color = Color.PINK;
				}else if(btn3.isSelected()) {
					color = Color.YELLOW;
				}
				//爲調色板設置背景色
				pallet.setBackground(color);
			}
		};
		//爲單選按鈕添加監聽器
		btn1.addActionListener(listener);
		btn2.addActionListener(listener);
		btn3.addActionListener(listener);
		this.setVisible(true);
	}
	
	public static void main(String[] args) {
		new example06();
	}
}

3.JComboBox

​ JComboBox組件被稱爲組合框還或者下拉列表框,它將所有選項摺疊收藏在一起,默認顯示的是第一個添加的選項。當用戶單擊組合框時,會出現下拉式的選擇列表,用戶可以從選擇其中一項並顯示。

​ JComboBox組合框組件分爲可編輯和不可編輯的兩種形式,對於不可編輯的組合框,用戶只能在現有選項列表中選擇,而對於可編輯的組合框,用戶既可以在現有的選項中選擇,也可以自己出入新的內容。需要注意的是,自己輸入的內容只能作爲當前項顯示,並不會添加到組合框的選項中。

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

/**
 * JComboBox組件
 */
public class example07 extends JFrame{
	public example07() {
		//創建JPanel面板
		JPanel panel = new JPanel();
		//創建一個下拉列表框
		final JComboBox<String> comboBox = new JComboBox<String>();
		//爲下拉列表框添加選擇
		comboBox.addItem("請選擇城市");
		comboBox.addItem("南陽");
		comboBox.addItem("杭州");
		comboBox.addItem("寧波");
		comboBox.addItem("上海");
		comboBox.addItem("廣州");
		
		//創建文本框
		JTextField field = new JTextField(20);
		//添加組件到面板中
		panel.add(comboBox);
		panel.add(field);
		
		//爲下拉列表框添加監聽器
		comboBox.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				String item = (String) comboBox.getSelectedItem();
				if("請選擇城市".equals(item)) {
					field.setText("");
				}else {
					field.setText("您選擇的城市是:"+item);
				}
			}
		});
		
		//把面板添加到窗體上
		this.add(panel);
		this.setSize(350,100);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setVisible(true);
		}
	public static void main(String[] args) {
		new example07();
	}
}

6.菜單組合

​ 在GUI程序中,菜單式很常見的組件,利用Swing提供的菜單組件可以創建出多種樣式的菜單。下面是下拉式菜單和彈出式菜單的介紹。

1.下拉式菜單

​ 下拉式菜單,是計算機中很多文件的菜單的首選,如記事本的菜單。在GUI程序中,創建下拉式菜單需要使用三個組件“:JMenuBar(菜單欄)、JMenu(菜單)和JMenultem(菜單項)。

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

public class example08 extends JFrame{
	public example08() {
		JMenuBar menuBar = new JMenuBar();//創建菜單欄
		JMenu menu = new JMenu("操作");//創建菜單
		JMenuItem item1 = new JMenuItem("彈出窗口");//創建兩個菜單項
		JMenuItem item2 = new JMenuItem("關閉");//創建兩個菜單項
		//組建下拉式菜單
		menu.add(item1);
		menu.addSeparator();//添加分隔符
		menu.add(item2);
		menuBar.add(menu);//菜單添加到菜單欄
		this.setJMenuBar(menuBar);//菜單欄添加到窗體
		this.setSize(300, 300);
		this.setLocationRelativeTo(null);
		this.setVisible(true);
		//爲菜單項添加事件的監聽器
		item1.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				JDialog dialog = new JDialog(example08.this,true);
				dialog.setTitle("彈出對話框");
				dialog.setSize(200, 200);
				dialog.setLocationRelativeTo(null);
				dialog.setVisible(true);
			}
		});
		
		item2.addActionListener(new ActionListener() {	
			@Override
			public void actionPerformed(ActionEvent e) {
				System.exit(0);
			}
		});
	}
	public static void main(String[] args) {
		new example08();
	}
}

2.彈出式菜單

​ 彈出式菜單,在Windows桌面單機鼠標右鍵會出現一個菜單,那就是彈出式菜單。在Java的Swing組件中,彈出式菜單用JPopupMenu表示。

​ JPopupMenu彈出式菜單和下拉式菜單一樣,都要通過調用add()方法添加JMenuItem菜單項,但他默認是不可見的。如果要顯示出來,則必須調用他的show(Component invoker,int x,int y)方法,該方法中參數invoker表示JPopupMenu菜單顯示位置的窗口組件,x和y表示invoker組件座標空間中的一個座標,顯示的是JPopMenu菜單的左上角座標。

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;

public class example09 extends JFrame{
	public example09() {
		//創建一個JPopopMenu菜單
		JPopupMenu  popupMenu = new JPopupMenu();
		//創建三個菜單項
		JMenuItem refreshItem = new JMenuItem("refresh");//刷新
		JMenuItem createItem = new JMenuItem("create");//新建
		JMenuItem exitItem = new JMenuItem("exit");//退出
		//把菜單項添加到菜單中
		popupMenu.add(refreshItem);
		popupMenu.addSeparator();//添加菜單項分隔符
		popupMenu.add(createItem);
		popupMenu.addSeparator();//添加菜單項分隔符
		popupMenu.add(exitItem);
		
		//爲當前窗體JFrame添加鼠標點擊事件
		this.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				//如果點擊的是鼠標的右鍵 ,顯示彈出菜單
				if(e.getButton() == e.BUTTON3) {
					popupMenu.show(e.getComponent(), e.getX(), e.getY());
				}
			}
		});
		this.setSize(300, 300);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setLocationRelativeTo(null);
		this.setVisible(true);
		//爲菜單項添加事件監聽器
		exitItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				System.exit(0);
			}
		});	
	}
	public static void main(String[] args) {
		new example09();
	}
}

7. JTable

​ 表格也是GUI程序中常用的組件,表格是一個由多行、多列組成的而未顯示區。Swing的JTable已經相關類提供了對這種表格的支持。使用了JTable以及相關類,程序既可以使用簡單代碼創建出表格來顯示二維數據,也可以開發出功能豐富的表格,還可以爲表格定製各種顯示外觀、編輯特性。

​ 使用JTable來創建表格是非常容易的事情,它可以把一個二維數據包裝成一個表格,這個二維數據既可以是一個二維數組,也可以是幾何元素Vector對象。除此之外,爲了給該表格的每一列指定列標題,還需要傳入一個一維數據作爲列標題,這個一維數據既可以是一維數據,也可以是Vector對象。

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
/**
 * JTable
 */
public class example10 extends JFrame{
	public example10() {
		init();//使用JTable對象創建表格
	}
	
	//使用JTable對象創建表格
	public void init() {
		//定義一個一維數組,作爲列的標題
		Object[] columnTitle = {"姓名","年齡","性別"};
		//定義一個二維數組,作爲表格行對象的數據
		Object[][] tableData = {
				new Object[] {"李清照","29","女"},
				new Object[] {"summer","20","男"},
				new Object[] {"茉莉","20","女"},
				new Object[] {"李白","38","男"},
		};
		//創建表格
		JTable table = new JTable(tableData,columnTitle);
		//添加表格組件到窗體上
		this.add(new JScrollPane(table));
		//設置自適應窗體大小
		this.pack();
		this.setTitle("簡單的表格");
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setLocationRelativeTo(null);
		this.setVisible(true);
	}
	public static void main(String[] args) {
		new example10();
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章