day23 GUI
1.?GUI編程引言
以前的學習當中,我們都使用的是命令交互方式:
例如:在DOS命令行中通過javac java命令啟動程序.
軟件的交互的方式:
1. 命令交互方式 ??
圖書管理系統
2. 圖形交互方式
Java提供了專業的API用于開發圖形用戶界面
GUI--> Graphic ?User ??Interface
將要了解GUI API的框架結構,以及GUI組件以及組件之間的關系,容器和布局管理器,顏色,字體等.
2.?GUI的分類
2.1.?AWT ?????
Java1.0版本的圖形用戶界面庫,設計目標是幫助程序員編寫在所有平臺上都能良好表現的GUI程序。為了實現這個目標Java1.0提供了抽象窗口工具集(AWT),但是這個目標并沒有達到。AWT在所有的系統上表現都不好。因為:最初版本的AWT是在一個月內構思,設計和實現的(Think in Java )。
Abstract ?Window ?Toolkit ??抽象窗口工具集
Java將圖形用戶界面相關的類捆綁在了一起,放在了一個稱之為抽象窗口工具集的庫中.AWT適合開發簡單的圖形用戶界面,并不適合開發復雜的GUI項目.
位于: java.awt.* 中,定義了很多的組件類,開發者可以直接創建對象加以使用
缺點: 所有的圖形界面都依賴于底層的操作系統,容易發生于特定平臺相關的故障.
AWT調用本地系統資源生成圖形化界面, 依賴本地平臺. 1.0
?
?
2.2.?Swing
SUN公司對AWT進行了升級,基于AWT,推出了一種更穩定,更通用和更靈活的庫.稱之為Swing組件庫(Swing component)。
既然都是用于GUI設計的組件庫,那么為了區分Swing組件類和對應的AWT組件類,Swing組件類都已字母J為前綴.位于:javax.swing.* 中,提供了和AWT中等同的所有的組件類,但是類名的前面多加了一個J.
SWING可以跨平臺. 1.2
我們主要學習Swing GUI組件.
3.?Java GUI API
GUI API包含的類分為三個部分:組件類(component class) 容器類(container class),和輔助類(helper class)
3.1.?組件類
在圖形用戶界面程序中當我們想要創建按鈕、復選框和滾動條等這些可以顯示在屏幕上的對象,該如何創建。其實這些都屬于一類叫做組件類。
AWT中的組件根類
| 類?Component java.lang.Object ??????????????????java.awt.Component |
Swing中的組件根類
| javax.swing 類?JComponent java.lang.Object ??????????????????java.awt.Component ????????????????????????java.awt.Container ??????????????????????????????javax.swing.JComponent |
?
組件類的實例可以顯示在屏幕上.Component類是包括容器類的所有用戶界面類的根類是java.awt中的類,對應的Swing中的是Jcomponent.了解了Component和JComponent都是抽象類.所以不能使用new關鍵字創建對象.所以需要使用它們的具體的實現類來創建對象.
在AWT中典型圖形用戶界面中的按鈕(Button)、復選框(Checkbox)和滾動條(Scrollbar)都是組件類,都是Component類的子類.
在Swing中的GUI組件,有對應的JButton,JCheckBox,JscrollBar
繼承關系圖(AWT)
?
3.2.?容器類
?
容器(Container),是一個特殊的組件,該組件可以通過add()添加其他組件。
容器類適用于盛裝其他GUI組件的GUI組件.例如 Panel Frame Dialog都是AWT組件的容器類.對應的Swing組件的容器類是JPanel JFrame JDialog
3.3.?GUI輔助類
用來描述GUI組件的屬性,例如圖像的顏色,字體等. 注意:輔助類是在java.awt中的
3.4.?GUI運行原理
在JDK的bin目錄中有javaw.exe .javaw.exe是java在window中專門用于執行GUI程序.
4.?體驗GUI
?
| import?javax.swing.JFrame; import?javax.swing.JOptionPane; ? public?class?Demo { public?static?void?main(String[] args) { // 創建JFrame JFrame frame = new?JFrame("hello,world"); // 設置尺寸 frame.setSize(200, 100); // JFrame在屏幕居中 frame.setLocationRelativeTo(null); // JFrame關閉時的操作 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 顯示JFrame frame.setVisible(true); ? } } ? |
?
5.?Jframe框架
?
JFrame(框架)是一個容器
創建一個用戶界面需要創建一個JFrame來存放用戶界面組件.例如存放按鈕,文本框。
| javax.swing 類 JFrame java.lang.Object ??java.awt.Component ??????java.awt.Container ??????????java.awt.Window ??????????????java.awt.Frame ??????????????????javax.swing.JFrame |
?
5.1.?創建一個框架
?
| public?class?Demo1 { public?static?void?main(String[] args) { // 創建JFrame JFrame frame = new?JFrame("我的frame"); // 顯示JFrame frame.setVisible(true); ? } } |
注意:需要調用setVisible(true)方法后才會顯示框架
運行程序會在窗口的左上角顯示一個窗口,但是只能顯示標題欄,而且關閉JFrame時,程序程序沒有停止.
所以需要完成如下需求:
1: 設置Jframe的寬度和高度
2: 讓Jframe顯示在屏幕中間
3: 關閉Jframe時,程序會停止
?
5.1.1.?設置JFrame的寬度和高度
| java.awt.Window.setSize(int width, int height) |
查找API文檔,查看 setSize方法,可以指定框架的寬度和高度.參數類型是int,注意是以像素為單位,普通的筆記本的屏幕分辨率為1280*800或者1366*768.注意:分辨率表示每平方英寸的像素數.屏幕分辨率越高,屏幕的像素越多.所以分辨率越高看到的細節就越多.
setSize方法被定義在java.awt.Component類中,被Component ?的子類java.awt.Window 重寫.而Jframe以繼承了Windiws類所以也具備該方法.
| ? |
5.1.2.?JFrame顯示在屏幕中間
setLocationRelativeTo()方法
| java.awt.Window.setLocationRelativeTo(Component c) 設置窗口相對于指定組件的位置。 如果?c?為 null,則此窗口將置于屏幕的中央。 |
setLocationRelativeTo(null)方法可以在屏幕上居中顯示框架.
?
如果不想要設置在中間,可以使用
| setLocation(200, 100); |
?
5.1.3.?關閉JFrame程序停止
setDefaultCloseOperation(int operation)方法
| javax.swing.JFrame.setDefaultCloseOperation(int operation) ? |
該方法告訴程序,當框架關閉時結束程序.方法的參數是JFrame 的常量EXIT_ON_CLOSE
?添加完畢
| public?class?Demo1 { public?static?void?main(String[] args) { // 創建JFrame JFrame frame = new?JFrame("我的frame"); // 設置尺寸 frame.setSize(200, 100); // JFrame在屏幕居中 frame.setLocationRelativeTo(null); // JFrame關閉時的操作 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 顯示JFrame frame.setVisible(true); ? } } |
5.2.?框架中添加組件
上述案例中的框架是空的.可以通過add方法在框架中添加組件
| java.awt.Container.add(Component comp) ? |
代碼:
| public?static?void?main(String[] args) { // 創建JFrame JFrame frame = new?JFrame("我的frame"); ? // 創建按鈕 JButton button = new?JButton("OK"); // 向frame中添加一個按鈕 frame.add(button); ? // 設置尺寸 frame.setSize(200, 100); // JFrame在屏幕居中 frame.setLocationRelativeTo(null); // JFrame關閉時的操作 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 顯示JFrame frame.setVisible(true); ? } |
?
?
?
?
運行程序,會顯示上圖所示窗口.調整窗口的大小,按鈕都是顯示在窗口的中央,并且占滿整個框架.這是因為組件(本例就是按鈕)是被布局管理器放到框架中的.默認布局管理器就是將按鈕放到中央.
?
備注: 可以通過f.setVisible(false); ?隱藏窗體f.dispose();關閉窗口
??設置圖片:
??setIconImage(Toolkit.getDefaultToolkit().createImage("png-0015.png"));
6.?JoptionPane對話框
顯示一個帶有OK?按鈕的模態對話框。
下面是幾個使用showMessageDialog?的例子:
Java代碼??
JOptionPane.showMessageDialog(null, "錯誤信息提示", "標題", JOptionPane.INFORMATION_MESSAGE);?效果如下:
?
Java代碼??
?效果如下:
Java代碼??
?
?
Java代碼??
?
?
1.2 showOptionDialog
這個函數可以改變顯示在按鈕上的文字。你還可以執行更多的個性化操作。
常規的消息框:
Java代碼??
?效果如下:
輸入框 :
String inputValue = JOptionPane.showInputDialog("請輸入你給我金額");
?
7.?面板(Panel)
面板也是一個容器的組件,可以在上面添加
?
注意:面板不能單獨使用,必須在頂層窗口中使用。
?
8.?常見組件
一些常用的組件例如:
JLabel,
JButton ,
JTextField
JPassworldField
JRadioButton
JCheckBox
JTextArea
JList
JMenuBar
JMenu
JMenultem
?
8.1.?Button按鈕
Java中的Swing提供了常規按鈕,單選按鈕,復選按鈕和菜單按鈕
8.1.1.?JButtion普通按鈕
按鈕Button是點擊時觸發動作事件的組件.
?
8.1.2.?JRadioButton單選按鈕
單選按鈕,可以讓用戶從一組選項中選擇一個單一條目.例如性別.
使用單選按鈕時注意將,單選按鈕放在一組,需要使用java.swing.ButtonGroup. 的add方法,添加到一個組中,位于同一個組的單選按鈕就是互斥的. 如果沒有將單選按鈕放在一個組中,就是獨立的..我們讓然需要把按鈕添加在容器中.因為ButtonGroup添加到容器中..
8.1.3.?JCheckBox復選框
多選
8.2.?JLabel標簽
8.3.?JTextField文本域
8.4.?JTextArea文本區域
8.5.?JComboBox組合框
8.6.?JList 列表框
例如: String[] data = { "one", "two", "three"?};
JList list = new?JList(data);
p1.add(list);
8.7.?JmenuBar菜單條
JMenu菜單
JMenultem菜單項
菜單條(MenuBar)中包含菜單(Menu),菜單中中包含菜單項(MenuItem)
注意添加的順序。例如:記事本的菜單條中包含文件、編輯、格式、查看、幫助菜單。其中文件菜單中包含新建、打開、保存、另存為等菜單項
?
案例綜合。
| public?class?CommonComponent?extends?JFrame { public?CommonComponent() { ? // 面板 JPanel p1 = new?JPanel(); add(p1); ? // 標簽 JLabel name = new?JLabel("用戶名:"); p1.add(name); ? // 文本域 JTextField field = new?JTextField(8); p1.add(field); ? // 標簽 JLabel passwd = new?JLabel("密碼"); p1.add(passwd); // 密碼域 JPasswordField pass = new?JPasswordField(8); p1.add(pass); ? // 單選按鈕 JLabel gender = new?JLabel("性別"); p1.add(gender); JRadioButton?male = new?JRadioButton("男"); JRadioButton?female = new?JRadioButton("女"); // 單選按鈕組,同一個單選按鈕組的互斥. ButtonGroup group = new?ButtonGroup(); group.add(male); group.add(female); // 注意,單選按鈕組不能添加進容器 p1.add(male); p1.add(female); ? // 復選框 JLabel like = new?JLabel("愛好:"); p1.add(like); JCheckBox eat = new?JCheckBox("吃飯"); JCheckBox movie = new?JCheckBox("看電影"); JCheckBox sleep = new?JCheckBox("睡覺"); p1.add(eat); p1.add(movie); p1.add(sleep); ? // 文本域 JLabel info = new?JLabel("個人簡介"); p1.add(info); JTextArea area = new?JTextArea(20, 20); p1.add(area); ? // 列表 String[] data = { "one", "two", "three"?}; JList list = new?JList(data); p1.add(list); ? // 普通按鈕 JButton button = new?JButton("注冊"); p1.add(button); ? // 菜單條 JMenuBar bar = new?JMenuBar(); // 菜單 JMenu menu = new?JMenu("文件"); // 菜單選項 JMenuItem myNew = new?JMenuItem("新建"); JMenuItem myOpen = new?JMenuItem("打開"); bar.add(menu); menu.add(myNew); menu.add(myOpen); add(bar, BorderLayout.NORTH); ? } ? public?static?void?main(String[] args) { CommonComponent frame = new?CommonComponent(); frame.setTitle("常用組件"); frame.setSize(400, 400); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 自適應 frame.pack(); frame.setVisible(true); } } ? |
?
樣式如下:
因為面板默認是流式布局.
?
?
9.?布局管理器
Java的GUI組件都放置在容器中,他們的位置是由容器的布局管理器來管理的.在前面的程序中,并沒有指定將OK按鈕放置在框架的什么位置,但是,Java知道應該把它放置在哪里,因為在后臺工作的布局管理器能夠將組件放到正確的位置.布局管理器是使用布局管理器類創建的.
我們可以使用setLayout() 方法在容器中設置布局管理器.
我們將要了解FlowLayout GridLayout BorderLayout
9.1.?FlowLayout流式布局
FlowLayout(流式布局)是最簡單布局管理器. Jpanel容器默認的布局管理器 ?
流式布局,按照組件添加的順序,從左到到右將組件排列在容器中.當放滿一行,就開始新的一行.在FlowLayout有3個常量FlowLayout可以指定組件的對齊方式.
LEFT ??每一行組件都應該是左對齊的
RIGHT ?每一行組件都應該是右對齊的
CENTER ?每一行組件都應該是居中的
還可以指定組件之間的以像素為單位的間隔.
| int getHgap() ??????????獲取組件之間以及組件與 Container 的邊之間的水平間隙。 int getVgap() ??????????獲取組件之間以及組件與 Container 的邊之間的垂直間隙。 void setHgap(int hgap) ??????????設置組件之間以及組件與 Container 的邊之間的水平間隙。 void setVgap(int vgap) ??????????設置組件之間以及組件與 Container 的邊之間的垂直間隙。 |
?
這個布局管理器的對其方式默認值是CENTER ?
這個布局管理器的水平間隔默認值是 5個像素
這個布局管理器的垂直間隔默認是是5個像素
創建該布局管理器
| FlowLayout() ??????????構造一個新的 FlowLayout,它是居中對齊的,默認的水平和垂直間隙是 5 個單位。 FlowLayout(int align) ??????????構造一個新的 FlowLayout,它具有指定的對齊方式,默認的水平和垂直間隙是 5 個單位。 FlowLayout(int align, int hgap, int vgap) ??????????創建一個新的流布局管理器,它具有指定的對齊方式以及指定的水平和垂直間隙。 ? |
?
案例:創建框架,使用流失布局管理器.向該框架添加三個標簽和文本域.
| public?class?ShowFlowLayout?extends?JFrame { ? public?ShowFlowLayout() { super.setLayout(new?FlowLayout(FlowLayout.LEFT, 10, 20)); ? add(new?JLabel("姓名:")); add(new?JTextField(8)); add(new?JLabel("郵箱:")); add(new?JTextField(8)); add(new?JLabel("電話:")); add(new?JTextField(8)); ? } ? public?static?void?main(String[] args) { ShowFlowLayout frame = new?ShowFlowLayout(); frame.setTitle("FlowLayout"); frame.setSize(500, 200); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } |
?
該案例在本類main方法中創建了一個本類對象. 該類的構造函數中創建并且添加組件.
該案例使用了FlowLayout管理器在框架放置組件.如果改變框架的大小.組建會自動的重新排列,以適應框架.
?
例如:
?
如果將同一個按鈕在框架中添加10次,那么該框架只會出現一次,將一個按鈕向容器中添加多以和一次是一樣的.
?
?
9.2.?GridLayout網格布局
GridLyaout是以網格形式管理組件的.組件按照他們添加的順序從左到右排列,顯示第一行,接著是第二行,一次類推.
Gridlayout可以指定網格中的行數和列數
規則如下:
行數和列數可以是0但是不能兩者都為0.
如果一個為0另外一個不為0,那么不為0的行或列的大小就是固定的,為0的行或者列有布局管理器動態決定.
例如:如果指定一個網格有0行3列10個組件,GirdLayout會創建3個固定的列和行,最后一行只有一個組件.如果指定一個網格有3行0列10個組件,GridLayout就會創建3行4列,最后一行包含2個組件.
如果行數和列數都不為0,那么以行數為依據.所以行數是固定的,布局管理器會動態的計算列數.例如,如果指定一個網格有3行3列10個組件,GridLayout會創建3個固定的行和4列,最后一行包含2個組件.
?
構造方法
| GridLayout() ??????????創建具有默認值的網格布局,即每個組件占據一行一列。 GridLayout(int rows, int cols) ??????????創建具有指定行數和列數的網格布局。 GridLayout(int rows, int cols, int hgap, int vgap) ??????????創建具有指定行數和列數,水平間隔,垂直間隔的網格布局。 ? |
方法:
| int getRows() ??????????獲取此布局中的行數。 默認值是1 int getColumns() ??????????獲取此布局中的列數。 默認值是1 ?int getHgap() ??????????獲取組件之間的水平間距。 默認值是0 int getVgap() ??????????獲取組件之間的垂直間距。默認值是0 ? 設置 void setRows(int rows) ??????????將此布局中的行數設置為指定值。默認值是1 void setColumns(int cols) ??????????將此布局中的列數設置為指定值。 ?默認值是1 ?void setHgap(int hgap) ??????????將組件之間的水平間距設置為指定值。 ?默認值是0 ?void setVgap(int vgap) ??????????將組件之間的垂直間距設置為指定值。默認值是0 ? |
?
案例:該案例依然添加3個標簽和3個文本域,只不過布局管理器是GrigLayout
| public?class?ShowGridLayout?extends?JFrame { public?ShowGridLayout() { setLayout(new?GridLayout(3, 2, 5, 5)); ? add(new?JLabel("姓名:")); add(new?JTextField(8)); add(new?JLabel("郵箱:")); add(new?JTextField(8)); add(new?JLabel("電話:")); add(new?JTextField(8)); } ? public?static?void?main(String[] args) { ShowGridLayout frame = new?ShowGridLayout(); frame.setTitle("GridLayout"); frame.setSize(200, 125); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } ? |
?
?
?
?
?
例如:
?
?
如果使用setLayout(new GridLayout(3,10))替換setlayout語句,還是會得到3行2列,因為行的參數非零,所以列的參數會被忽略.列的實際參數是由布局管理器計算出來的.
9.3.?BorderLayout邊框布局
邊框布局,JFrame 容器默認的布局管理器是邊框布局.該管理器將容器非為東西南北中5個區域.我們使用add(Component,index)方法可以將組件添加進到BorderLayout中,index是一個常量,有5個值
| EAST ??????????東區域的布局約束(容器右邊)。 WEST ??????????西區域的布局約束(容器左邊)。 SOUTH ??????????南區域的布局約束(容器底部)。 NORTH ??????????北區域的布局約束(容器頂部)。 CENTER ??????????中間區域的布局約束(容器中央)。 |
?
構造函數
| BorderLayout() ??????????構造一個組件之間沒有間距的新邊框布局。 BorderLayout(int hgap, int vgap) ??????????構造一個具有指定組件間距的邊框布局。 ? |
?
方法:
| int getHgap() ??????????返回組件之間的水平間距。 int getVgap() ??????????返回組件之間的垂直間距。 void setHgap(int hgap) ??????????設置組件之間的水平間距。 默認值是0 ?void setVgap(int vgap) ??????????設置組件之間的垂直間距。默認值是0 ? |
?
組件會根據他們最合適的尺寸和在容器中的位置來放置,南北組件可以水平拉伸,東西組件可以垂直拉伸,中央組件既可以水平拉伸也可以垂直拉伸.
案例:演示邊框布局管理器
| public?class?ShowBorderLayout?extends?JFrame { public?ShowBorderLayout() { setLayout(new?BorderLayout(5, 10)); ? add(new?JButton("東"), BorderLayout.WEST); add(new?JButton("西"), BorderLayout.EAST); add(new?JButton("南"), BorderLayout.SOUTH); add(new?JButton("北"), BorderLayout.NORTH); add(new?JButton("中"), BorderLayout.CENTER); } ? public?static?void?main(String[] args) { ShowBorderLayout frame = new?ShowBorderLayout(); frame.setTitle("BorderLayout"); frame.setSize(300, 200); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } ? |
?
?
?
?
注意: 如果布局管理器為Border管理器,調用add方法,沒有說明組件的位置(東西南北中)默認是center.
所以
add(new?JButton("ok"))和 add(new?JButton("ok"), BorderLayout.CENTER?)
效果是一樣的.
如果在Border容器中添加2個組件,都沒有指定位置,那么只會顯示最后一個組件
add(new?JButton("ok1"))和add(new?JButton("ok2")) 只會顯示ok2
?
使用布局管理器
代碼:
| public?class?CommonComponent?extends?JFrame { public?CommonComponent() { // 菜單條 JMenuBar bar = new?JMenuBar(); // 菜單 JMenu menu = new?JMenu("文件"); // 菜單選項 JMenuItem myNew = new?JMenuItem("新建"); JMenuItem myOpen = new?JMenuItem("打開"); bar.add(menu); menu.add(myNew); menu.add(myOpen); add(bar, BorderLayout.NORTH); ? // 面板 JPanel p1 = new?JPanel(); p1.setLayout(new?GridLayout(2, 2, 5, 5)); add(p1); ? // 標簽 JLabel name = new?JLabel("用戶名:"); p1.add(name); ? // 文本域 JTextField field = new?JTextField(8); p1.add(field); ? // 標簽 JLabel passwd = new?JLabel("密碼"); p1.add(passwd); // 密碼域 JPasswordField pass = new?JPasswordField(8); p1.add(pass); ? JPanel p2 = new?JPanel(); // 單選按鈕 JLabel gender = new?JLabel("性別"); p2.add(gender); JRadioButton male = new?JRadioButton("男"); JRadioButton female = new?JRadioButton("女"); // 單選按鈕組,同一個單選按鈕組的互斥. ButtonGroup group = new?ButtonGroup(); group.add(male); group.add(female); // 注意,單選按鈕組不能添加進容器 p2.add(male); p2.add(female); ? JPanel p3 = new?JPanel(); // 復選框 JLabel like = new?JLabel("愛好:"); p3.add(like); JCheckBox eat = new?JCheckBox("吃飯"); JCheckBox movie = new?JCheckBox("看電影"); JCheckBox sleep = new?JCheckBox("睡覺"); p3.add(eat); p3.add(movie); p3.add(sleep); ? JPanel p4 = new?JPanel(new?GridLayout(1, 0, 5, 5)); // 文本域 JLabel info = new?JLabel("個人簡介:"); p4.add(info); JTextArea area = new?JTextArea(50, 10); p4.add(area); ? JPanel p5 = new?JPanel(new?BorderLayout()); // 列表 String[] data = { "one", "two", "three"?}; JList list = new?JList(data); p5.add(list, BorderLayout.WEST); ? JPanel p6 = new?JPanel(); // 普通按鈕 JButton button = new?JButton("注冊"); p6.add(button); JButton button2 = new?JButton("取消"); p6.add(button2); ? setLayout(new?GridLayout(7, 1, 5, 5)); add(p1); add(p2); add(p3); add(p4); add(p5); add(p6); ? } ? public?static?void?main(String[] args) { CommonComponent frame = new?CommonComponent(); frame.setTitle("常用組件"); frame.setSize(400, 600); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 自適應 // frame.pack(); frame.setVisible(true); } } |
格式如下:
| ? |
?
需求:需要在一個Jframe框架中放置10個按鈕和一個文本域.
?
要求按鈕以網格形式放置,文本域單獨一行.
如果將這些組件放在一個單獨的容器中,很難達要去的效果.我們使用Java圖形用戶界面進行程序設計時,可以將一個窗口分成幾個面板Jpanel.面板的作用就是分組放置用戶界面的子容器.這里可以將按鈕添加到一個面板中,然后經面板添加到框架中.
在Swing中的面板是JPanel 可以使用new Jpanel () 創建一個默認是FlowLayout管理器的面板,也可以使用newJPanel(LayoutManager) 創建一個帶特定布局管理器的面板.使用add方法將組件添加進面板中.
例如:
| public?class?ShowJPanel?extends?JFrame { ShowJPanel() { JButton button = new?JButton("ok"); JPanel jPanel = new?JPanel(); jPanel.add(button); add(jPanel); } ? public?static?void?main(String[] args) { ShowJPanel frame = new?ShowJPanel(); frame.setTitle("面板"); frame.setSize(200, 200); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } |
?
?
圖示:
| 進按鈕添加進面板面板添加進容器 ??? ??? |
?
| 進按鈕直接添加進框架. ? ? |
???
案例:
| public?class?TestPanel?extends?JFrame { public?TestPanel() { // 創建面板,默認是流式布局 JPanel p1 = new?JPanel(); // 指定為網格布局,4行3列 p1.setLayout(new?GridLayout(4, 3)); for?(int?i = 1; i <=9; i++) { p1.add(new?JButton(""?+ i)); } p1.add(new?JButton("0")); p1.add(new?JButton("OK")); p1.add(new?JButton("EXIT")); ? // 創建面板,指定邊框布局 JPanel p2 = new?JPanel(new?BorderLayout()); // 面板添加文本域,邊框北部 p2.add(new?JTextField("我在這里啊!!!"), BorderLayout.NORTH); // 面板添加其他面板,邊框中部. p2.add(p1, BorderLayout.CENTER); ? // 框架添加面板,框架的布局默認就是邊框布局,面板指定位于框架西部 add(p2, BorderLayout.EAST); // 框架添加按鈕,位于框架總部. add(new?JButton("哈哈"), BorderLayout.CENTER); ? } ? public?static?void?main(String[] args) { TestPanel frame = new?TestPanel(); frame.setTitle("JPanel"); frame.setSize(400, 260); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } ? |
該案例中創建了兩個面板(Jpanel) , 面板的默認布局是流式布局.,可以使用setLayout 更改面板的布局( setLayout 是java.awt.Container定義的, Jpanel 是Container的子類).
該案例中
面板p1布局指定為GridLayout(網格布局)將12個按鈕,添加進面板p1中.
面板p2 布局指定為BorderLayout,將p1面板添加進來, p1位于該面板的中部.再添加一個文本域,位于面板p2北部.
將面板p2添加進框架(框架布局默認為BorderLayout),位于框架的西部,在框架的中部添加一個按鈕.
效果:
?
注意: 面板容器是一個輕量級的容器,該容器不能單獨的使用,必須依賴與外層的頂層容器(JFrame)
?
10.?Java事件監聽機制
在上述的程序中,其中菜單條,菜單項,按鈕等都是對象,當我們單擊對象時,應該能夠完成一些任務.例如在程序中通過鼠標操作時,單擊,雙擊,鼠標移入,鼠標移出.能夠執行一些任務,在Java中我們可以使用事件監聽機制,在Java的事件監聽機制中?,當事件發生時(點擊按鈕,移動鼠標等,關閉窗口)會被一類對象發現并處理.
?
?
10.1.?事件和事件源
在運行java圖形用戶界面程序時,用戶與程序交互,用戶執行了某些操作時,會發生一些事情,?那么事件(event)可以定義為程序發生了某些事情的信號.典型用戶操作就是用戶移動鼠標,點擊按鈕,敲擊鍵盤等.程序可以選擇相應事件或者忽略事件。
能夠創建一個事件并觸發該事件的組件稱為源對象。例如由于按鈕能夠點擊, 那么按鈕就是一個源對象,按鈕被點擊就是一個事件。
一個事件是事件類的實例對象。事件類的根類是java.util.EventObject。
事件對象包含事件相關的屬性,可以使用EventObject類中的實例方法getSource獲得事件的源對象。
EventObject類的子類可以描述特定類型的事件
例如:
| 用戶動作 | 源對象 | 觸發的事件類型 |
| 點擊按鈕 | JButton | ActionEvent |
| 文本域按回車 | JTextField | ActionEvent |
| 窗口打開,關閉,最小化,關閉 | Window | WindowEvent |
| 單擊,雙擊,移動,鼠標 | Component | MouseEvent |
| 點擊單選框 | JradioButton | ItemEvent ActionEvent |
| 點擊復選框 | JcheckBox | ItemEvent ActionEvent |
?
10.2.?監聽器
當源對象觸發了一個事件,誰來處理這個事件?在Java中對此感興趣的對象會處理它。對此感興趣的對象稱之為監聽器(Listener)。
舉例來說當我們點擊一個按鈕,想要按鈕執行一些動作,需要一個對象來監控按鈕,當點擊按鈕的事件發生時,該對象就會監聽到按鈕事件。進而可以執行一些動作。
例如:
?
Java中,對象表示的每個事件都是由java.util中EventObject類的子類,
例如: MouseEvent: 表示鼠標的動作,例如移動光標,單擊,雙擊
KeyEvent: 表示鍵盤上的按鍵.
ActionEvent表示用戶采取的用戶界面操作,例如點擊屏幕上的按鈕.
10.3.?事件處理
Java對組件都有對應的事件監聽器,和添加事件監聽器方法。
例如: 按鈕: 源對象,會觸發
體驗:當用戶點擊按鈕時,按鈕上的信息會發生變化
| import?java.awt.event.ActionEvent; import?java.awt.event.ActionListener; import?javax.swing.JButton; import?javax.swing.JFrame; ? public?class?ShowButton?extends?JFrame { public?ShowButton() { JButton button = new?JButton("點我"); add(button); ? // 添加鼠標監聽事件 button.addActionListener(new?ActionListener() { ? @Override public?void?actionPerformed(ActionEvent e) { System.out.println("按鈕被點擊"); Object source = e.getSource(); JButton button = (JButton) source; String text = button.getText(); if?("按鈕被點擊".equals(text)) { button.setText("點我"); } else?{ button.setText("按鈕被點擊"); } } }); } ? public?static?void?main(String[] args) { ShowButton frame = new?ShowButton(); frame.setTitle("我的框架"); frame.setSize(400, 200); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } |
該案例中:構造方法創建了用戶界面。只有一個JFrame框架和一個按鈕。
按鈕時事件的源。創建了一個監聽器并注冊到了按鈕。通過匿名內部類的形式創建了監聽器類
10.4.?窗口事件
Window類
| java.awt 類?Window java.lang.Object ??????java.awt.Component ?????????????java.awt.Container ???????????????????java.awt.Window |
Window?對象是一個頂層窗口。窗口(Window)對應的事件叫做窗口事件(WindowEvent),任何窗口(Window)以及窗口的子類都可能觸發窗口事件: 打開窗口,正在關閉窗口,激活窗口,變成非活動窗口,最小化窗口和還原窗口。
Window添加窗口事件(WindowEvent)監聽器的方法
| void addWindowListener(WindowListener l) ??????????添加指定的窗口偵聽器,以從此窗口接收窗口事件 ? |
監聽Window窗口事件(WindowEvent)的監聽器:WindowListener
| java.awt.event 接口?WindowListener 用于接收窗口事件的偵聽器接口。當通過打開、關閉、激活或停用、圖標化或取消圖標化而改變了窗口狀態時,將調用該偵聽器對象中的相關方法 ? |
WindowListener接口中定義的方法
| 抽象方法: void windowActivated(WindowEvent e) ??????????激活窗口 ?void windowClosed(WindowEvent e) ??????????關閉窗口 ?void windowClosing(WindowEvent e) ??????????正在關閉窗口 ?void windowDeactivated(WindowEvent e) ??????????變為非活動窗口 ?void windowDeiconified(WindowEvent e) ??????????還原窗口 ??? ?void windowIconified(WindowEvent e) ??????????最小化窗口 void windowOpened(WindowEvent e) ???????????打開窗口 ?? ? |
?
?
?
案例: 框架的事件監聽處理
| javax.swing 類?JFrame java.lang.Object ???????java.awt.Component ??????????????java.awt.Container ????????????????????java.awt.Window ??????????????????????????java.awt.Frame ????????????????????????????????javax.swing.JFrame |
?
創建JFrame,Jfame是一個框架,屬于窗體(Window)體系中的一員,也可以實現窗口的最大化,最小化,關閉,點擊窗體,等一系列的操作。那么在用戶觸發這些事件發生時能夠做一些工作,就需要注冊事件監聽器。
?
JFrame 是通過addWindowListener 方法就注冊窗體事件監聽器,該方法需要接受一個監聽器(WindowListener)對象。查找API文檔,發現WindowListener是一個接口,
我們需要窗口監聽器(WindowListener)的實例對象,所以需要實現該接口,重寫WindowListener接口的抽象方法。然后創建該實現類對象,作為參數傳遞給addWindowListener .
例如: 當像激活窗口這樣的窗口事件發生時,windowActivated?方法就會觸發。
代碼如下:
| import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import javax.swing.JFrame; ? public class WindowEventDemo extends JFrame { ? WindowEventDemo() { // this對象時JFrame的子類,而JFrame 類是Window體系中的一員所以具備添加窗口事件的方法 this.addWindowListener(new MyWindow()); } ? public static void main(String[] args) { WindowEventDemo frame = new WindowEventDemo(); frame.setTitle("我的框架"); frame.setSize(400, 200); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } ? // 實現WindowListener class MyWindow implements WindowListener { // 激活窗口 public void windowActivated(WindowEvent e) { System.out.println("激活窗口"); } ? // 關閉窗口 public void windowClosed(WindowEvent e) { System.out.println("關閉窗口"); } ? // 正在關閉窗口 public void windowClosing(WindowEvent e) { System.out.println("正在關閉窗口"); } ? // 變為非活動窗口 public void windowDeactivated(WindowEvent e) { System.out.println("變為非活動窗口"); } ? // 還原窗口 public void windowDeiconified(WindowEvent e) { System.out.println("還原窗口"); } ? // 最小化窗口 public void windowIconified(WindowEvent e) { System.out.println(" 最小化窗口"); } ? // 打開窗口 public void windowOpened(WindowEvent e) { System.out.println("打開窗口"); } ? } |
總結:Window類或者Window類的任何子類都可能會觸發WindowEvent。因為JFrame是Window的子類。所以也可以觸發WindowEvent。
10.5.?監聽器接口適配器
因為WindowListener接口中的方法都是抽象的,所以即使程序中不想關注某些事件,但是還是要實現所以的方法,比較麻煩,為了方便起見,Java提供了一個針對WindowListener接口的實現類,該類中把WindowListener接口中的方法全部實現,只不過方法體都為空。
例如: 加入我們只對激活窗口感興趣,那么只需要繼承該實現類重寫激活窗口的方法即可。簡化了代碼。
| import?java.awt.event.WindowAdapter; import?java.awt.event.WindowEvent; import?javax.swing.JFrame; ? public?class?AdapterDemo?extends?JFrame { AdapterDemo() { addWindowListener(new?MyAdapter()); } ? public?static?void?main(String[] args) { AdapterDemo frame = new?AdapterDemo(); frame.setTitle("我的框架"); frame.setSize(400, 200); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } ? class?MyAdapter extends?WindowAdapter { public?void?windowActivated(WindowEvent e) { System.out.println("windowActivated...."); } } ? } ? |
那么這個WindowAdapter類就叫做適配器類,是為了簡化代碼的書寫而出現的。
| 適配器 ???????????????????????????接口 ??? WindowAdapter ??????????????WindowListener MouserAdapter ?MouserListener KeyAdapter ???????? ?KeyListener ? |
?
10.6.?鼠標鍵盤事件
當在一個組件上按下,釋放,點擊,移動,或者拖動鼠標時,就會產生鼠標事件。MouseEvent對象捕獲這個事件。
MouseEvent
| java.awt.event.MouseEvent |
?
Java對鼠標事件提供了MouseListener 監聽器接口,可以監聽鼠標的按下,釋放,輸入,退出和點擊動作。
MouseListener
用于接收組件上“感興趣”的鼠標事件(按下、釋放、單擊、進入或離開)的偵聽器接口
方法:
| void mouseClicked(MouseEvent e) ??????????鼠標按鍵在組件上單擊(按下并釋放)時調用。 ?void mouseEntered(MouseEvent e) ??????????鼠標進入到組件上時調用。 ?void mouseExited(MouseEvent e) ??????????鼠標離開組件時調用。 ?void mousePressed(MouseEvent e) ??????????鼠標按鍵在組件上按下時調用。 ?void mouseReleased(MouseEvent e) ??????????鼠標按鈕在組件上釋放時調用。 ? |
?
?
按鍵事件可以利用鍵盤來控制和執行一些動作,如果按下、釋放一個鍵就會觸發按鍵事件。KeyEvent對象可以捕獲按鍵的按下放開和敲擊。KeyEvent提供了getkeyChar 來獲取按鍵對應的字符。
| java.awt.event.KeyEvent ? char getKeyChar() ??????????返回與此事件中的鍵關聯的字符。 |
?
Java提供了KeyListener監聽器接口來監聽按鍵事件。
?
KeyListener接口
用于接收鍵盤事件(擊鍵)的偵聽器接口。
| void keyPressed(KeyEvent e) ??????????按下某個鍵時調用此方法。? ?void keyReleased(KeyEvent e) ??????????釋放某個鍵時調用此方法。? ?void keyTyped(KeyEvent e) ??????????鍵入某個鍵時調用此方法。 ? |
?
案例:
?
演示鼠標事件和鍵盤事件,當在文本域中輸入q 時程序會退出。
| public?class?MouseEventDemo?extends?JFrame { MouseEventDemo() { JButton button = new?JButton("ok"); JTextArea text = new?JTextArea(); add(button, BorderLayout.NORTH); add(text, BorderLayout.CENTER); ? button.addMouseListener(new?MouseListener() { ? // 鼠標按鈕在組件上釋放時調用。 public?void?mouseReleased(MouseEvent e) { System.out.println("鼠標釋放"); ? } ? // 鼠標按鍵在組件上按下時調用。 public?void?mousePressed(MouseEvent e) { System.out.println("鼠標按下組件"); ? } ? // 鼠標離開組件時調用。 public?void?mouseExited(MouseEvent e) { System.out.println("鼠標離開組件"); ? } ? // 鼠標進入到組件上時調用。 public?void?mouseEntered(MouseEvent e) { // 鼠標進入 System.out.println("鼠標進入組件"); ? } ? // 鼠標按鍵在組件上單擊(按下并釋放)時調用。 public?void?mouseClicked(MouseEvent e) { System.out.println("鼠標單擊組件"); ? } }); text.addKeyListener(new?KeyListener() { ? // 鍵入某個鍵時調用此方法。 public?void?keyTyped(KeyEvent e) { System.out.println("鍵入某個鍵"); if?(e.getKeyChar() == 'q') { System.exit(0); } } // 釋放某個鍵時調用此方法。 public?void?keyReleased(KeyEvent e) { System.out.println("按鍵釋放"); ? } ? // 按下某個鍵時調用此方法。 public?void?keyPressed(KeyEvent e) { System.out.println("鍵盤按下"); } }); } ? public?static?void?main(String[] args) { MouseEventDemo frame = new?MouseEventDemo(); frame.setTitle("鼠標事件"); frame.setSize(400, 200); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } ? |
?
?
10.7.?事件監聽機制小結
一:確定事件源(容器或組件)
二:注冊監聽器
l ?通過事件源對象的addXXXListener()方法將監聽器對象注冊到該事件源上。
三:監聽器對象
l???注冊監聽器時,需要指定監聽器對象。
以參數的形式進監聽器對象傳遞給addXXXListener()
監聽器對象是XXXListener的子類對象或者XXXAdapter的子類對象。
l 監聽器對象一般用匿名內部類來表示。(簡化書寫)
l 在覆蓋方法的時候,方法的參數一般是XXXEvent類型的變量接收。
l ?事件觸發后會把事件打包成對象傳遞給該變量。(其中包括事件源對象。通過getSource()或者getComponent()獲取。)
四:常見的事件監聽器
WindowListener ???????主要用于監聽窗口
ActionListener ?????????主要用于用監聽組件對象的單擊動作
MouseListener ?????????鼠標監聽器
KeyListener ??????????????監聽鍵盤
…….
五:常見的事件適配器
WindowAdapter
MouseAdapter
KeyAdapter
?
轉載于:https://www.cnblogs.com/yukai123/p/6992069.html
總結
- 上一篇: 三个案例,解读静态代码块和构造代码块
- 下一篇: ArcGIS 网络分析[8.2] 资料2