java必學(xué)必會之GUI編程
一、事件監(jiān)聽

測試代碼一:
package cn.javastudy.summary;
import java.awt.*;
import java.awt.event.*;
public class TestTextField {
public static void main(String args[]) {
new MyFrameTextField();
}
}
class MyFrameTextField extends Frame {
MyFrameTextField() {
TextField tf = new TextField();
add(tf);
tf.addActionListener(new Monitor3());
tf.setEchoChar('*');
/*
* 這個setEchoChar()方法是設(shè)置文本框輸入時顯示的字符,這里設(shè)置為*,
* 這樣輸入任何內(nèi)容就都以*顯示出來,不過打印出來時依然可以看到輸入的內(nèi)容
*/
setVisible(true);
pack();
}
}
class Monitor3 implements ActionListener {
/*
* 接口里面的所有方法都是public(公共的)
* 所以從API文檔復(fù)制void actionPerformed(ActionEvent e)時 要在void前面加上public
*/
public void actionPerformed(ActionEvent e) {
/* 事件的相關(guān)信息都封裝在了對象e里面,通過對象e的相關(guān)方法就可以獲取事件的相關(guān)信息 */
TextField tf = (TextField) e.getSource();
/*
* getSource()方法是拿到事件源,注意:拿到這個事件源的時候,
* 是把它當(dāng)作TextField的父類來對待
* getSource()方法的定義是:“public Object getSource()”返回值是一個Object對象,
* 所以要強(qiáng)制轉(zhuǎn)換成TextField類型的對象
* 在一個類里面想訪問另外一個類的事件源對象可以通過getSource()方法
*/
System.out.println(tf.getText());// tf.getText()是取得文本框里面的內(nèi)容
tf.setText("");// 把文本框里面的內(nèi)容清空
}
}
測試代碼二:
package cn.javastudy.summary;
import java.awt.*;
import java.awt.event.*;
public class TestActionEvent2{
public static void main(String args[]){
Frame f = new Frame("TestActionEvent");
Button btn1 = new Button("start");
Button btn2 = new Button("stop");
Monitor2 m2 = new Monitor2();//創(chuàng)建監(jiān)聽對象
btn1.addActionListener(m2);
/*一個監(jiān)聽對象同時監(jiān)聽兩個按鈕的動作*/
btn2.addActionListener(m2);
btn2.setActionCommand("GameOver");//設(shè)置btn2的執(zhí)行單擊命令后的返回信息
f.add(btn1,BorderLayout.NORTH);
f.add(btn2,BorderLayout.CENTER);
f.pack();
f.setVisible(true);
}
}
class Monitor2 implements ActionListener{
public void actionPerformed(ActionEvent e){
System.out.println("a button has been pressed,"+"the relative info is:\n"+e.getActionCommand());
/*使用返回的監(jiān)聽對象e調(diào)用getActionCommand()方法獲取兩個按鈕執(zhí)行單擊命令后的返回信息
根據(jù)返回信息的不同區(qū)分開當(dāng)前操作的是哪一個按鈕,btn1沒有使用setActionCommand()方法設(shè)置
則btn1返回的信息就是按鈕上顯示的文本*/
}
}
二、TextField事件監(jiān)聽

測試代碼:
package cn.javastudy.summary;
import java.awt.*;
import java.awt.event.*;
public class TestTextField {
public static void main(String args[]) {
new MyFrameTextField();
}
}
class MyFrameTextField extends Frame {
MyFrameTextField() {
TextField tf = new TextField();
add(tf);
tf.addActionListener(new Monitor3());
tf.setEchoChar('*');
/*
* 這個setEchoChar()方法是設(shè)置文本框輸入時顯示的字符,這里設(shè)置為*,
* 這樣輸入任何內(nèi)容就都以*顯示出來,不過打印出來時依然可以看到輸入的內(nèi)容
*/
setVisible(true);
pack();
}
}
class Monitor3 implements ActionListener {
/*
* 接口里面的所有方法都是public(公共的)
* 所以從API文檔復(fù)制void actionPerformed(ActionEvent e)時 要在void前面加上public
*/
public void actionPerformed(ActionEvent e) {
/* 事件的相關(guān)信息都封裝在了對象e里面,通過對象e的相關(guān)方法就可以獲取事件的相關(guān)信息 */
TextField tf = (TextField) e.getSource();
/*
* getSource()方法是拿到事件源,注意:拿到這個事件源的時候,
* 是把它當(dāng)作TextField的父類來對待
* getSource()方法的定義是:“public Object getSource()”返回值是一個Object對象,
* 所以要強(qiáng)制轉(zhuǎn)換成TextField類型的對象
* 在一個類里面想訪問另外一個類的事件源對象可以通過getSource()方法
*/
System.out.println(tf.getText());// tf.getText()是取得文本框里面的內(nèi)容
tf.setText("");// 把文本框里面的內(nèi)容清空
}
}
使用TextField類實現(xiàn)簡單的計算器
package cn.javastudy.summary;
import java.awt.*;
import java.awt.event.*;
public class TestMath {
public static void main(String args[]) {
new TFFrame();
}
}
/* 這里主要是完成計算器元素的布局 */
class TFFrame extends Frame {
TFFrame() {
/*
* 創(chuàng)建3個文本框,并指定其初始大小分別為10個字符和15個字符的大小 這里使用的是TextField類的另外一種構(gòu)造方法 public TextField(int columns)
*/
TextField num1 = new TextField(10);
TextField num2 = new TextField(10);
TextField num3 = new TextField(15);
/* 創(chuàng)建等號按鈕 */
Button btnEqual = new Button("=");
btnEqual.addActionListener(new MyMonitor(num1, num2, num3));
/* 給等號按鈕加上監(jiān)聽,讓點擊按鈕后有響應(yīng)事件發(fā)生 */
Label lblPlus = new Label("+");
/* “+”是一個靜態(tài)文本,所以使用Label類創(chuàng)建一個靜態(tài)文本對象 */
setLayout(new FlowLayout());
/* 把Frame默認(rèn)的BorderLayout布局改成FlowLayout布局 */
add(num1);
add(lblPlus);
add(num2);
add(btnEqual);
add(num3);
pack();
setVisible(true);
}
}
class MyMonitor implements ActionListener {
TextField num1, num2, num3;
/*
* 為了使對按鈕的監(jiān)聽能夠?qū)ξ谋究蛞财鹱饔茫?
* 所以在自定義類MyMonitor里面定義三個TextField類型的對象 num1,num2,num3,
* 并且定義了MyMonitor類的一個構(gòu)造方法 這個構(gòu)造方法帶有三個TextField類型的參數(shù),
* 用于接收 從TFFrame類里面?zhèn)鬟f過來的三個TextField類型的參數(shù)
* 然后把接收到的三個TextField類型的參數(shù)賦值給在本類中聲明的 三個TextField類型的參數(shù)num1,num2,num3 然后再在actionPerformed()方法里面處理num1,num2,num3
*/
public MyMonitor(TextField num1, TextField num2, TextField num3) {
this.num1 = num1;
this.num2 = num2;
this.num3 = num3;
}
public void actionPerformed(ActionEvent e) {
/* 事件的相關(guān)信息都封裝在了對象e里面,通過對象e的相關(guān)方法就可以獲取事件的相關(guān)信息 */
int n1 = Integer.parseInt(num1.getText());/* num1對象調(diào)用getText()方法取得自己顯示的文本字符串 */
int n2 = Integer.parseInt(num2.getText());/* num2對象調(diào)用getText()方法取得自己顯示的文本字符串 */
num3.setText("" + (n1 + n2));/* num3對象調(diào)用setText()方法設(shè)置自己的顯示文本 */
num1.setText("");
/* 計算結(jié)束后清空num1,num2文本框里面的內(nèi)容 */
num2.setText("");
// num3.setText(String.valueOf((n1+n2)));
/* 字符串與任意類型的數(shù)據(jù)使用“+”連接時得到的一定是字符串,
* 這里使用一個空字符串與int類型的數(shù)連接,這樣就可以直接把(n1+n2)得到的int類型的數(shù)隱式地轉(zhuǎn)換成字符串了,
* 這是一種把別的基礎(chǔ)數(shù)據(jù)類型轉(zhuǎn)換成字符串的一個小技巧。
* 也可以使用“String.valueOf((n1+n2))”把(n1+n2)的和轉(zhuǎn)換成字符串
*/
}
}
JAVA里面的經(jīng)典用法:在一個類里面持有另外一個類的引用
package cn.javastudy.summary;
import java.awt.*;
import java.awt.event.*;
public class TestMath1 {
public static void main(String args[]) {
new TTMyFrame().launchFrame();
/* 創(chuàng)建出TTMyFrame對象后調(diào)用lauchFrame()方法把計算器窗體顯示出來 */
}
}
/* 做好計算器的窗體界面 */
class TTMyFrame extends Frame {
/* 把設(shè)計計算器窗體的代碼封裝成一個方法 */
TextField num1, num2, num3;
public void launchFrame() {
num1 = new TextField(10);
num2 = new TextField(15);
num3 = new TextField(15);
Label lblPlus = new Label("+");
Button btnEqual = new Button("=");
btnEqual.addActionListener(new MyMonitorbtnEqual(this));
setLayout(new FlowLayout());
add(num1);
add(lblPlus);
add(num2);
add(btnEqual);
add(num3);
pack();
setVisible(true);
}
}
/*
* 這里通過取得TTMyFrame類的引用,然后使用這個引用去訪問TTMyFrame類里面的成員變量
* 這種做法比上一種直接去訪問TTMyFrame類里面的成員變量要好得多,
* 因為現(xiàn)在不需要知道 TTMyFrame類里面有哪些成員變量了,
* 現(xiàn)在要訪問TTMyFrame類里面的成員變量,直接使用 TTMyFrame類對象的引用去訪問即可,
* 這個TTMyFrame類的對象好比是一個大管家, 而我告訴大管家,我要訪問TTMyFrame類里面的那些成員變量,
* 大管家的引用就會去幫我找,不再需要我自己去找了。
* 這種在一個類里面持有另一個類的引用的用法是一種非常典型的用法
* 使用獲取到的引用就可以在一個類里面訪問另一個類的所有成員了
*/
class MyMonitorbtnEqual implements ActionListener {
TTMyFrame ttmf = null;
public MyMonitorbtnEqual(TTMyFrame ttmf) {
this.ttmf = ttmf;
}
public void actionPerformed(ActionEvent e) {
int n1 = Integer.parseInt(ttmf.num1.getText());
int n2 = Integer.parseInt(ttmf.num2.getText());
ttmf.num3.setText("" + (n1 + n2));
ttmf.num1.setText("");
ttmf.num2.setText("");
}
}
運行結(jié)果如下:

三、內(nèi)部類

內(nèi)部類的使用范例:
package cn.javastudy.summary;
import java.awt.*;
import java.awt.event.*;
public class TestMath3 {
public static void main(String args[]) {
new MyMathFrame().launchFrame();
}
}
class MyMathFrame extends Frame {
TextField num1, num2, num3;
public void launchFrame() {
num1 = new TextField(10);
num2 = new TextField(15);
num3 = new TextField(15);
Label lblPlus = new Label("+");
Button btnEqual = new Button("=");
btnEqual.addActionListener(new MyMonitor());
setLayout(new FlowLayout());
add(num1);
add(lblPlus);
add(num2);
add(btnEqual);
add(num3);
pack();
setVisible(true);
}
/*
* 這個MyMonitor類是內(nèi)部類,它在MyFrame類里面定義 MyFrame類稱為MyMonitor類的包裝類
*/
/*
* 使用內(nèi)部類的好處:
* 第一個巨大的好處就是可以暢通無阻地訪問外部類(即內(nèi)部類的包裝類)的所有成員變量和方法
* 如這里的在MyFrame類(外部類)定義的三個成員變量num1,num2,num3,
* 在MyMonitor(內(nèi)部類)里面就可以直接訪問
* 這相當(dāng)于在創(chuàng)建外部類對象時內(nèi)部類對象默認(rèn)就擁有了一個外部類對象的引用
*/
private class MyMonitor implements ActionListener {
public void actionPerformed(ActionEvent e) {
int n1 = Integer.parseInt(num1.getText());
int n2 = Integer.parseInt(num2.getText());
num3.setText("" + (n1 + n2));
num1.setText("");
num2.setText("");
}
}
}
內(nèi)部類帶來的巨大好處是:
- 可以很方便地訪問外部類定義的成員變量和方法
- 當(dāng)某一個類不需要其他類訪問的時候就把這個類聲明為內(nèi)部類。
四、Graphics 類

測試代碼:
package cn.javastudy.summary;
import java.awt.*;
public class TestPaint{
public static void main(String args[]){
new MyPaint().launchFrame();
/*在main()方法里面并沒有顯示調(diào)用paint(Graphics g)方法
可是當(dāng)創(chuàng)建出Frame窗體后卻可以看到Frame窗體上畫出了
圓和矩形,這是因為paint()方法是一個比較特殊的方法
在創(chuàng)建Frame窗體時會自動隱式調(diào)用
當(dāng)我們把Frame窗體最小化又再次打開時,又會再次調(diào)用
paint()方法重新把圓和矩形在Frame窗體上畫出來
即每次需要重畫Frame窗體的時候就會自動調(diào)用paint()方法*/
}
}
class MyPaint extends Frame{
public void launchFrame(){
setBounds(200,200,640,480);
setVisible(true);
}
public void paint(Graphics g){
/*paint(Graphics g)方法有一個Graphics類型的參數(shù)g
我們可以把這個g當(dāng)作是一個畫家,這個畫家手里拿著一只畫筆
我們通過設(shè)置畫筆的顏色與形狀來畫出我們想要的各種各樣的圖像*/
/*設(shè)置畫筆的顏色*/
g.setColor(Color.red);
g.fillOval(100,100,100,100);/*畫一個實心橢圓*/
g.setColor(Color.green);
g.fillRect(150,200,200,200);/*畫一個實心矩形*/
/*這下面的兩行代碼是為了寫程序的良好編程習(xí)慣而寫的
前面設(shè)置了畫筆的顏色,現(xiàn)在就應(yīng)該把畫筆的初始顏色恢復(fù)過來
就相當(dāng)于是畫家用完畫筆之后把畫筆上的顏色清理掉一樣*/
Color c = g.getColor();
g.setColor(c);
}
}
運行結(jié)果:

五、鼠標(biāo)事件適配器

測試代碼:
package cn.galc.test;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class MyMouseAdapter{
public static void main(String args[]) {
new MyFrame("drawing...");
}
}
class MyFrame extends Frame {
ArrayList points = null;
MyFrame(String s) {
super(s);
points = new ArrayList();
setLayout(null);
setBounds(300,300,400,300);
this.setBackground(new Color(204,204,255));
setVisible(true);
this.addMouseListener(new Monitor());
}
public void paint(Graphics g) {
Iterator i = points.iterator();
while(i.hasNext()){
Point p = (Point)i.next();
g.setColor(Color.BLUE);
g.fillOval(p.x,p.y,10,10);
}
}
public void addPoint(Point p){
points.add(p);
}
}
class Monitor extends MouseAdapter {
public void mousePressed(MouseEvent e) {
MyFrame f = (MyFrame)e.getSource();
f.addPoint(new Point(e.getX(),e.getY()));
f.repaint();
}
}
六、window事件

測試代碼:
package cn.galc.test;
import java.awt.*;
import java.awt.event.*;
public class TestWindowClose{
public static void main(String args[]){
new WindowFrame("關(guān)閉WindowFrame");
}
}
class WindowFrame extends Frame{
public WindowFrame(String s){
super(s);
setBounds(200,200,400,300);
setLayout(null);
setBackground(new Color(204,204,255));
setVisible(true);
this.addWindowListener(new WindowMonitor());
/*監(jiān)聽本窗體的動作,把所有的動作信息封裝成一個對象傳遞到監(jiān)聽類里面*/
this.addWindowListener(
/*在一個方法里面定義一個類,這個類稱為局部類,也叫匿名的內(nèi)部類,
這里的{……代碼……}里面的代碼很像一個類的類體,只不過這個類沒有名字,所以叫匿名類
在這里是把這個匿名類當(dāng)成WindowAdapter類來使用,語法上這樣寫的本質(zhì)意義是相當(dāng)于這個匿名類
從WindowAdapter類繼承,現(xiàn)在new了一個匿名類的對象出來然后把這個對象當(dāng)成WindowAdapter來使用
這個匿名類出了()就沒有人認(rèn)識了*/
new WindowAdapter(){
public void windowClosing(WindowEvent e){
setVisible(false);
System.exit(-1);
}
}
);
}
/*這里也是將監(jiān)聽類定義為內(nèi)部類*/
class WindowMonitor extends WindowAdapter{
/*WindowAdapter(Window適配器)類實現(xiàn)了WindowListener監(jiān)聽接口
重寫了WindowListener接口里面的所有方法
如果直接使用自定義WindowMonitor類直接去
實現(xiàn)WindowListener接口,那么就得要重寫WindowListener接口
里面的所有方法,但現(xiàn)在只需要用到這些方法里面的其中一個方法
所以采用繼承實現(xiàn)WindowListener監(jiān)聽接口的一個子類
并重寫這個子類里面需要用到的那個方法即可
這種做法比直接實現(xiàn)WindowListener監(jiān)聽接口要重寫很多個用不到的方法要簡潔方便得多*/
/*重寫需要用到的windowClosing(WindowEvent e)方法*/
public void windowClosing(WindowEvent e){
setVisible(false);/*將窗體設(shè)置為不顯示,即可實現(xiàn)窗體關(guān)閉*/
System.exit(0);/*正常退出*/
}
}
}
七、鍵盤響應(yīng)事件——KeyEvent
測試代碼:
package cn.galc.test;
import java.awt.*;
import java.awt.event.*;
public class TestKeyEvent{
public static void main(String args[]){
new KeyFrame("鍵盤響應(yīng)事件");
}
}
class KeyFrame extends Frame{
public KeyFrame(String s){
super(s);
setBounds(200,200,400,300);
setLayout(null);
setVisible(true);
addKeyListener(new KeyMonitor());
}
/*把自定義的鍵盤的監(jiān)聽類定義為內(nèi)部類
這個監(jiān)聽類從鍵盤適配器KeyAdapter類繼承
從KeyAdapter類繼承也是為了可以簡潔方便
只需要重寫需要用到的方法即可,這種做法比
直接實現(xiàn)KeyListener接口要簡單方便,如果
直接實現(xiàn)KeyListener接口就要把KeyListener
接口里面的所有方法重寫一遍,但真正用到的
只有一個方法,這樣重寫其他的方法但又用不到
難免會做無用功*/
class KeyMonitor extends KeyAdapter{
public void keyPressed(KeyEvent e){
int keycode = e.getKeyCode();
/*使用getKeyCode()方法獲取按鍵的虛擬碼*/
/*如果獲取到的鍵的虛擬碼等于up鍵的虛擬碼
則表示當(dāng)前按下的鍵是up鍵
KeyEvent.VK_UP表示取得up鍵的虛擬碼
鍵盤中的每一個鍵都對應(yīng)有一個虛擬碼
這些虛擬碼在KeyEvent類里面都被定義為靜態(tài)常量
所以可以使用“類名.靜態(tài)常量名”的形式訪問得到這些靜態(tài)常量*/
if(keycode == KeyEvent.VK_UP){
System.out.println("你按的是up鍵");
}
}
}
}
/*鍵盤的處理事件是這樣的:每一個鍵都對應(yīng)著一個虛擬的碼,
當(dāng)按下某一個鍵時,系統(tǒng)就會去找這個鍵對應(yīng)的虛擬的碼,以此來確定當(dāng)前按下的是那個鍵
*/
通過這篇文章和大家一起學(xué)習(xí)了GUI編程,希望大家對GUI編程有了更全面的認(rèn)識,關(guān)于GUI編程遠(yuǎn)不止這些,還需要大家繼續(xù)學(xué)習(xí)。
相關(guān)文章
Spring Security+JWT實現(xiàn)認(rèn)證與授權(quán)的實現(xiàn)
本文主要介紹了Spring Security+JWT實現(xiàn)認(rèn)證與授權(quán)的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04
Springboot過濾器禁止ip頻繁訪問功能實現(xiàn)
這篇文章主要介紹了Springboot過濾器禁止ip頻繁訪問功能實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-04-04
SpringBoot實現(xiàn)MQTT消息發(fā)送和接收方式
這篇文章主要介紹了SpringBoot實現(xiàn)MQTT消息發(fā)送和接收方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03
Spring Boot 中的自動配置autoconfigure詳解
這篇文章主要介紹了Spring Boot 中的自動配置autoconfigure詳解,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2024-01-01

