文章目錄
零、本講學習目標
1、熟悉JFrame和JDialog頂級容器的基本使用
2、掌握Swing的常用佈局管理器的使用
一、Swing概述
要不要學習Swing或者AWT這個問題,完全取決於個人的發展方向。嚴格說來,如果你以後想要從事Web方向的開發,確實可以不用學習,但是如果以後想要從事GUI編程或者C/S編程的工作,那麼肯定是要學習Swing相關知識的。
軟件開發中,語言都是相通的,沒有哪個語言優於哪個語言的說法。俗話說,書到用時方恨少,知識也是一樣,患寡不患多。從整個Java體系來看,要想全面地熟悉Java語言,還是需要學會GUI編程的,畢竟這也是Java大體系裏面不可缺少的一環。熟悉GUI編程對於以後的開發也大有裨益。
(一)AWT是何物?
1、AWT定義
在早期JDK1.0發佈時,Sun公司就爲GUI開發提供了一套基礎類庫,這套類庫被稱爲AWT(Abstract Window Toolkit
),即抽象窗口工具包。AWT起初設想就是爲了統一實現不同操作系統的圖像界面。
2、AWT缺陷
- 不同操作系統圖形庫的功能可能不一樣,在一個平臺上存在的功能在另外一個平臺上則可能不存在,爲此AWT不得不通過犧牲功能來實現平臺無關性。
- AWT是一個重量級組件,使用麻煩,設計出的圖形界面不夠美觀且功能有限。
(二)Swing是何物?
1、Swing定義
Swing是在原有的AWT的基礎上進行了補充和改進,提供了更加豐富的組件和功能,來滿足GUI設計的一切需求。
2、Swing與AWT的關係
- Swing是一種輕量級組件,它由Java語言開發,同時底層以AWT爲基礎。
- 同AWT相比,在實際開發中,更多的是使用Swing進行圖形用戶界面開發。
- Swing組件爲實現圖形用戶界面提供了很多基礎類庫,多數位於java.awt、javax.swing包及其子包下。
3、Swing組件繼承關係圖
- Swing組件的所有類都繼承自Container類,然後根據GUI開發的功能擴展了2個主要分支:容器分支(包括Window窗口和Panel面板)和組件分支。
- 容器分支就是爲了實現圖形用戶界面窗口容器而設計的。
- 組件分支則是爲了實現向容器中填充數據、元素以及人機交互組件等功能。
- Swing組件類中,常用的頂級容器類包括有JApplet、JFrame和JDialog。
- 常用組件AbstractButton類及其子類是用來定義按鈕常見行爲的工具類。
- JTextComponent類及其子類就是用來定義文本內容編輯區域的工具類。
二、Swing頂級容器
Swing提供了三個主要的頂級容器類:JFrame、JDialog和JApplet,其中JFrame和JDialog是最爲常用也是最爲簡單的頂級容器,下面我們就一起來學習如何使用這兩種頂級容器。
(一)JFrame - 窗口
1、JFrame概述
- 在Swing組件中,最常見的一個容器就是JFrame。
- JFrame是一個獨立存在的頂級容器(也叫窗口),不能放置在其他容器之中。
- JFrame支持通用窗口所有的基本功能,例如窗口最小化、設定窗口大小等。
2、JFrame繼承關係圖
3、JFrame常用構造方法
方法聲明 | 功能描述 |
---|---|
JFrame() | 創建一個窗體對象,不指定標題 |
JFrame(String title) | 創建一個窗體對象,並指定標題 |
在實際開發中,我們用得最多的是第二個構造方法,參數用於指定窗口的標題:
4、案例演示:創建登錄窗口
現在我們只能創建一個空的登錄窗口,等我們學習了佈局管理器與常用的組件(標籤、文本框與按鈕),我們就可以改進這個程序,做出一個可以輸入用戶名與密碼的登錄窗口。
- 繼承JFrame類,創建登錄窗口類LoginFrame
- 編寫應用程序框架
package net.hw.lesson29;
import javax.swing.*;
import java.awt.*;
/**
* 功能:創建登錄窗口
* 作者:華衛
* 日期:2020年05月30日
*/
public class LoginFrame extends JFrame {
/**
* 構造方法
*
* @param title
* @throws HeadlessException
*/
public LoginFrame(String title) throws HeadlessException {
super(title); // 調用父類構造方法傳入標題參數
initGUI(); // 調用初始化圖形用戶界面方法
}
/**
* 初始化圖形用戶界面方法
*/
private void initGUI() {
}
/**
* 主方法
*
* @param args
*/
public static void main(String[] args) {
// 實例化登錄窗口對象
LoginFrame loginFrame = new LoginFrame("登錄窗口");
}
}
- 編寫initGUI()方法
private void initGUI() {
// 設置窗口邊界
setBounds(200, 200, 300, 200);
// 設置窗口可見
setVisible(true);
}
-
運行程序,查看結果
-
簡要說明
– 如果不設置窗口初始位置,那麼只需要調用setSize()方法,設置窗口的寬度與高度
– 窗口出現後,單擊關閉按鈕,窗口消失不見了,但是應用程序或進程還未結束,必須單擊工具欄上那個紅色的停止按鈕,強行終止應用程序,可以看到進程結束的退出碼是-1。 -
修改代碼,讓窗口啓動時屏幕居中顯示,單擊關閉按鈕就退出應用程序
private void initGUI() {
// 設置窗口邊界
setBounds(200, 200, 300, 200);
// 設置屏幕居中(採用相對定位方式)
setLocationRelativeTo(null);
// 設置窗口可見
setVisible(true);
// 設置默認關閉方式(關閉窗口就退出應用程序)
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
- 運行程序,查看效果
5、課堂練習:創建並顯示一個窗口
- 創建Exercise2901
- 在主方法裏創建窗口對象,設置窗口標題“學生信息”
- 設置窗口尺寸,寬度400,高度300
- 設置窗口啓動時屏幕居中
- 設置窗口的可見屬性,將窗口顯示在屏幕上
- 設置窗口關閉方式,關閉窗口即退出應用程序
(二)JDialog - 對話框
1、JDialog概述
Dialog是Swing的另外一個頂級容器,通常用來表示對話框窗口。
JDialog對話框可分爲兩種:模態對話框和非模態對話框。
- 模態對話框是指用戶需要等到處理完對話框後才能繼續與其他窗口交互。
- 非模態對話框是指允許用戶在處理對話框的同時還可以與其他窗口交互。
對話框是模態或者非模態,可以在創建JDialog對象時爲構造方法傳入參數來設置,也可以在創建JDialog對象後調用它的setModal()方法來進行設置。
2、JDialog繼承關係圖
3、JDialog常用構造方法
方法聲明 | 功能描述 |
---|---|
JDialog(Frame owner) | 構造方法,用來創建一個非模態的對話框,owner爲對話框所有者(頂級窗口JFrame) |
JDialog(Frame owner,String title) | 構造方法,創建一個具有指定標題的非模態對話框 |
JDialog(Frame owner,boolean modal) | 創建一個有指定模式的無標題對話框,默認值false(即非模態對話框) |
4、案例演示:顯示窗口與對話框
- 創建Example2901
package net.hw.lesson29;
import javax.swing.*;
/**
* 功能:顯示窗口與對話框
* 作者:華衛
* 日期:2020年05月30日
*/
public class Example2901 {
/**
* 初始化圖形用戶界面
*/
public static void initGUI() {
// 創建窗口對象
JFrame frame = new JFrame("JFrame窗口");
// 設置窗口邊界
frame.setBounds(200, 200, 300, 200);
// 設置屏幕居中(採用相對定位方式)
frame.setLocationRelativeTo(null);
// 設置窗口可見
frame.setVisible(true);
// 設置默認關閉方式(關閉窗口就退出應用程序)
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 基於窗口創建對話框對象
JDialog dialog = new JDialog(frame, "JDialog對話框", true);
// 設置默認關閉方式(關閉對話框就隱藏對話框)
dialog.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
// 設置對話框大小
dialog.setSize(200, 100);
// 設置對話框在窗口居中
dialog.setLocationRelativeTo(frame);
// 設置對話框可見
dialog.setVisible(true);
}
public static void main(String[] args) {
// 使用SwingUtils工具類調用initGUI()方法
SwingUtilities.invokeLater(Example2901::initGUI);
}
}
- 運行程序,查看結果
- 簡單說明
– 雖然JFrame和JDialog都可以創建頂級容器窗口,但JDialog創建的窗口右上角沒有放大和縮小功能。
– 由於創建JDialog容器對象時,設置的模態參數modal爲true,所以在操作時,必須先關閉JDialog對話框後纔可以與JFrame窗口進行交互。
三、佈局管理器
(一)佈局管理器概述
Swing組件不能單獨存在,必須放置於容器當中,而組件在容器中的位置和尺寸是由佈局管理器來決定的。
(二)佈局管理器分類
(三)邊界佈局管理器(BorderLayout)
1、邊界佈局管理器概述
BorderLayout(邊界佈局管理器)是一種較爲複雜的佈局方式,它將容器劃分爲五個區域,分別是頁頭(PAGE_START
)、頁尾(PAGE_END
)、行首(LINE_START
)、行尾(LINE_END
)、中部(CENTER
)。組件可以被放置在這五個區域中的任意一個位置。
2、邊界佈局管理器使用方法
- 向BorderLayout佈局管理器的容器中添加組件時,需要使用add(Component comp, Object constraints)方法。
- 參數comp表示要添加的組件,constraints指定將組件添加到佈局中的位置,它是一個Object類型。
- 傳參時可以使用BorderLayout類提供的5個常量設置組件位置,它們分別是
PAGE_START
、PAGE_END
、LINE_START
、LINE_END
和CENTER
。 - BorderLayout的好處就是可以限定各區域的邊界,當用戶改變容器窗口大小時,各個組件的相對位置不變。
- 向BorderLayout的佈局管理器添加組件時,如果不指定添加到哪個區域,則默認添加到CENTER區域。
- 每個區域只能放置一個組件,如果向一個區域中添加多個組件時,後放入的組件會覆蓋先放入的組件。
3、案例演示:演示邊界佈局效果
- 繼承JFrame,創建BorderLayoutDemo
package net.hw.lesson29;
import javax.swing.*;
import java.awt.*;
/**
* 功能:演示邊界佈局效果
* 作者:華衛
* 日期:2020年05月30日
*/
public class BorderLayoutDemo extends JFrame {
public BorderLayoutDemo(String title) throws HeadlessException {
super(title); // 調用父類構造方法傳入標題參數
initGUI(); // 調用初始化圖形用戶界面方法
}
/**
* 初始化圖形用戶界面方法
*/
private void initGUI() {
// 設置邊界佈局管理器
setLayout(new BorderLayout());
// 設置窗口邊界
setBounds(200, 200, 400, 300);
// 設置屏幕居中(採用相對定位方式)
setLocationRelativeTo(null);
// 創建五個按鈕
JButton btnNorth = new JButton("北方");
JButton btnSouth = new JButton("南方");
JButton btnWest = new JButton("西方");
JButton btnCenter = new JButton("中原");
JButton btnEast = new JButton("東方");
// 添加按鈕到窗口指定區域
add(btnNorth, BorderLayout.PAGE_START); // BorderLayout.NORTH
add(btnSouth, BorderLayout.PAGE_END); // BorderLayout.SOUTH
add(btnWest, BorderLayout.LINE_START); // BorderLayout.WEST
add(btnCenter, BorderLayout.CENTER);
add(btnEast, BorderLayout.LINE_END); // BorderLayout.EAST
// 設置窗口可見
setVisible(true);
// 設置默認關閉方式(關閉窗口就退出應用程序)
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new BorderLayoutDemo("演示邊界佈局");
}
}
- 運行程序,查看結果
4、溫馨小貼士
在使用BorderLayout邊界佈局管理器過程中,當使用add(Component comp,Object constraints)方法向容器區域中添加指定組件和位置時,除了可以使用前面介紹的PAGE_START、PAGE_END、LINE_START、LINE_END和CENTER常量參數指定組件位置,也可以使用NORTH、SOUTH、EAST、WEST和CENTER常量參數來指定組件位置,只不過案例BorderLayoutDemo裏使用的常量參數是JDK 1.4版本開始出現的,適合不同語言標準,也是官方相對推薦的。
(四)流式佈局管理器(FlowLayout)
1、流式佈局管理器概述
- FlowLayout(流式佈局管理器)是最簡單的佈局管理器。
- 在這種佈局下,容器會將組件按照添加順序從左向右放置,當到達容器的邊界時,會自動將組件放到下一行的開始位置。
- 這些組件可以按左對齊、居中對齊(默認方式)或右對齊的方式排列。
2、流式佈局管理器構造方法
方法聲明 | 功能描述 |
---|---|
FlowLayout() | 組件默認居中對齊,水平、垂直間距默認爲5個單位 |
FlowLayout(int align) | 指定組件相對於容器的對齊方式,水平、垂直間距默認爲5個單位 |
FlowLayout(int align, int hgap, int vgap) | 指定組件的對齊方式和水平、垂直間距 |
- 參數align決定組件在每行中相對於容器邊界的對齊方式,分別爲左對齊、右對齊、居中對齊。
- 對齊方式可以使用該類中提供的常量
FlowLayout.LEFT
、FlowLayout.RIGHT
、FlowLayout.CENTER
表示。 - 參數hgap和參數vgap分別設定組件之間的水平和垂直間距,可以填入一個任意數值。
3、案例演示:演示流式佈局效果
- 繼承JFrame,創建FlowLayoutDemo
package net.hw.lesson29;
import javax.swing.*;
import java.awt.*;
/**
* 功能:演示流式佈局效果
* 作者:華衛
* 日期:2020年05月30日
*/
public class FlowLayoutDemo extends JFrame {
public FlowLayoutDemo(String title) throws HeadlessException {
super(title); // 調用父類構造方法傳入標題參數
initGUI(); // 調用初始化圖形用戶界面方法
}
/**
* 初始化圖形用戶界面方法
*/
private void initGUI() {
// 設置流式佈局管理器
setLayout(new FlowLayout(FlowLayout.LEFT, 20, 30));
// 設置窗口邊界
setBounds(200, 200, 400, 300);
// 設置屏幕居中(採用相對定位方式)
setLocationRelativeTo(null);
// 創建五個按鈕
JButton button1 = new JButton("第一個按鈕");
JButton button2 = new JButton("第二個按鈕");
JButton button3 = new JButton("第三個按鈕");
JButton button4 = new JButton("第四個按鈕");
JButton button5 = new JButton("第五個按鈕");
// 添加按鈕到窗口
add(button1);
add(button2);
add(button3);
add(button4);
add(button5);
// 設置窗口可見
setVisible(true);
// 設置默認關閉方式(關閉窗口就退出應用程序)
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new FlowLayoutDemo("演示流式佈局");
}
}
- 運行程序,查看結果
(五)網格佈局管理器(GridLayout)
1、網格佈局管理器概述
- GridLayout(網格佈局管理器)使用縱橫線將容器分成n行m列大小相等的網格,每個網格中可以添加一個組件。
- 添加到容器中的組件會從左向右、從上向下依次填充到網格中。
- 與FlowLayout不同的是,放置在GridLayout佈局管理器中的組件將自動佔據網格的整個區域
2、網格佈局管理器構造方法
方法聲明 | 功能描述 |
---|---|
GridLayout() | 默認只有一行,每個組件佔一列 |
GridLayout(int rows, int cols) | 指定容器的行數和列數 |
GridLayout(int rows, int cols, int hgap, int vgap) | 指定容器的行數和列數以及組件之間的水平、垂直間距 |
- 說明:參數rows代表行數,cols代表列數,hgap和vgap規定窗格之間水平和垂直方向的間距。
3、網格佈局特點
對於網格佈局,組件的相對位置不隨區域的縮放而改變,但組件的大小會隨之改變,組件始終佔據網格的整個區域。存在一個缺點:總是忽略組件的最佳大小,所有組件的寬高都相同。
4、案例演示:演示網格佈局效果
- 繼承JFrame,創建GridLayoutDemo
package net.hw.lesson29;
import javax.swing.*;
import java.awt.*;
/**
* 功能:演示網格佈局效果
* 作者:華衛
* 日期:2020年05月30日
*/
public class GridLayoutDemo extends JFrame {
public GridLayoutDemo(String title) throws HeadlessException {
super(title); // 調用父類構造方法傳入標題參數
initGUI(); // 調用初始化圖形用戶界面方法
}
/**
* 初始化圖形用戶界面方法
*/
private void initGUI() {
// 設置網格佈局管理器
setLayout(new GridLayout(3, 3, 10, 5));
// 設置窗口邊界
setBounds(200, 200, 400, 300);
// 設置屏幕居中(採用相對定位方式)
setLocationRelativeTo(null);
// 創建五個按鈕
JButton button1 = new JButton("第一個按鈕");
JButton button2 = new JButton("第二個按鈕");
JButton button3 = new JButton("第三個按鈕");
JButton button4 = new JButton("第四個按鈕");
JButton button5 = new JButton("第五個按鈕");
JButton button6 = new JButton("第六個按鈕");
JButton button7 = new JButton("第七個按鈕");
JButton button8 = new JButton("第八個按鈕");
// 添加按鈕到窗口
add(button1);
add(button2);
add(button3);
add(button4);
add(button5);
add(button6);
add(button7);
add(button8);
// 設置窗口可見
setVisible(true);
// 設置默認關閉方式(關閉窗口就退出應用程序)
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new GridLayoutDemo("演示網格佈局");
}
}
- 運行程序,查看結果
四、利用佈局管理器與組件改進登錄窗口
- 修改LoginFrame的initGUI()方法,設置佈局,添加面板與組件
package net.hw.lesson29;
import javax.swing.*;
import java.awt.*;
/**
* 功能:創建登錄窗口
* 作者:華衛
* 日期:2020年05月30日
*/
public class LoginFrame extends JFrame {
/**
* 構造方法
*
* @param title
* @throws HeadlessException
*/
public LoginFrame(String title) throws HeadlessException {
super(title); // 調用父類構造方法傳入標題參數
initGUI(); // 調用初始化圖形用戶界面方法
}
/**
* 初始化圖形用戶界面方法
*/
private void initGUI() {
// 創建三個面板
JPanel panel1 = new JPanel();
JPanel panel2 = new JPanel();
JPanel panel3 = new JPanel();
// 獲取內容面板
JPanel panel = (JPanel) getContentPane();
// 設置面板panel的佈局爲表格佈局
panel.setLayout(new GridLayout(3,1));
// 將三個小面板添加到面板panel裏
panel.add(panel1);
panel.add(panel2);
panel.add(panel3);
/* 第一個面板裏要添加用戶名標籤與文本框 */
// 創建用戶名標籤
JLabel lblUsername = new JLabel("用戶名:");
// 創建用戶名文本框
JTextField txtUsername = new JTextField(15);
// 將標籤與文本框添加到第一個面板
panel1.add(lblUsername);
panel1.add(txtUsername);
/* 第二個面板裏要添加密碼標籤與文本框 */
// 創建密碼標籤
JLabel lblPassword = new JLabel("密 碼:");
// 創建密碼文本框
JPasswordField txtPassword = new JPasswordField(15);
// 將標籤與文本框添加到第二個面板
panel2.add(lblPassword);
panel2.add(txtPassword);
/* 第三個面板裏要添加兩個按鈕 */
// 創建登錄按鈕
JButton btnLogin = new JButton("登錄");
// 創建取消按鈕
JButton btnCancel = new JButton("取消");
// 將兩個按鈕添加到第三個面板
panel3.add(btnLogin);
panel3.add(btnCancel);
// 設置窗口邊界
setBounds(200, 200, 300, 200);
// 設置屏幕居中
setLocationRelativeTo(null);
// 設置窗口緊湊
pack();
// 設置窗口可見
setVisible(true);
// 設置默認關閉方式
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
/**
* 主方法
*
* @param args
*/
public static void main(String[] args) {
// 實例化登錄窗口對象
LoginFrame loginFrame = new LoginFrame("登錄窗口");
JDialog dialog;
}
}
- 運行程序,查看結果
- 可以在用戶名與密碼文本框裏輸入數據,並且密碼文本框回顯的是一串大圓點
- 單擊【確定】和【取消】按鈕,沒有任何反應,因爲我們還沒有編寫事件處理方法
- 下一講,我們會學習Swing事件處理機制,然後我們再來改進這個登錄窗口程序。
五、課後作業:創建修改密碼窗口
- 繼承JFrame,創建ChangePasswordFrame
- 設置佈局,添加組件,設置窗口屬性
- 用戶名文本框不可用(調用setEnabled()方法,傳入false參數)
- 給兩個按鈕設置熱鍵字母(調用setMnemonic()方法)
btnOK = new JButton("確定[O]");
btnOK.setMnemonic(KeyEvent.VK_O);
btnCancel = new JButton("取消[C]");
btnCancel.setMnemonic(KeyEvent.VK_C);