Java基础学习总结(23)——GUI编程
一、AWT介绍
所有的可以显示出来的图形元素都称为Component,Component代表了所有的可见的图形元素,Component里面有一种比较特殊的图形元素叫Container,Container(容器)在图形界面里面是一种可以容纳其它Component元素的一种容器,Container本身也是一种Component的,Container里面也可以容纳别的Container。
Container里面又分为Window和Pannel,Window是可以独立显示出来的,平时我们看到的各种各样的应用程序的窗口都可以称为Window,Window作为一个应用程序窗口独立显示出来,Pannel也可以容纳其它的图形元素,但一般看不见Pannel,Pannel不能作为应用程序的独立窗口显示出来,Pannel要想显示出来就必须得把自己装入到Window里面才能显示出来。
Pannel应用比较典型的就是Applet(JAVA的页面小应用程序),现在基本上已经不用了,AJAX和JAVASCRIPT完全取代了它的应用。
Window本身又可以分为Frame和Dialog,Frame就是我们平时看到的一般的窗口,而Dialog则是那些需要用户进行了某些操作(如点击某个下拉菜单的项)才出现的对话框,这种对话框就是Dialog。
二、组件和容器(Component和Container)
2.1.Frame
Frame范例:
1 package cn.javastudy.summary; 2 3 /**学习JAVA的GUI编程编写的第一个图形界面窗口*/ 4 import java.awt.*; 5 6 public class TestFrame { 7 public static void main(String args[]) { 8 Frame f = new Frame("我的第一个JAVA图形界面窗口"); 9 /* 10 * 这里只是在内存里面创建了一个窗口对象 还不能真正显示出来然我们看到 11 */ 12 f.setBackground(Color.blue);// 设置窗体的背景颜色 13 // blue是Color类里面的一个静态常量,可以使用“类名.静态常量名”来访问 14 f.setVisible(true);// 设置窗体是否可见 15 /* 16 * 要想看到在内存里面创建出来的窗口对象, 必须调用setVisble()方法,并且把参数true传入才能看得见窗体 如果传入的参数是false,那么窗体也是看不见的 17 */ 18 f.setSize(400, 400);// 设置窗体的初始大小 19 f.setLocation(200, 200);// 设置窗体出现时的位置,如果不设置则默认在左上角(0,0)位置显示 20 f.setResizable(false); 21 /* 22 * 设置窗体能否被改变大小,设置为false后表示不能改变窗体的显示大小 这里将窗体显示的大小设置为200X200,那么窗体的显示只能是这个大小了,不能再使用鼠标拖大或者缩小 23 */ 24 } 25 }
运行结果如下:
1 package cn.javastudy.summary; 2 3 import java.awt.*; 4 public class TestMultiFrame{ 5 public static void main(String args[]){ 6 MyFrame f1 = new MyFrame(100,100,200,200,Color.BLUE); 7 MyFrame f2 = new MyFrame(300,100,200,200,Color.YELLOW); 8 MyFrame f3 = new MyFrame(100,300,200,200,Color.GREEN); 9 MyFrame f4 = new MyFrame(300,300,200,200,Color.MAGENTA); 10 } 11 } 12 /*自定义一个类MyFrame,并且从Frame类继承 13 这样MyFrame类就拥有了Frame类的一切属性和方法 14 并且MyFrame类还可以自定义属性和方法 15 因此使用从Frame类继承而来的自定义类来创建图形窗口比直接使用Frame类来创建图形窗口要灵活 16 所以一般使用从Frame类继承而来的自定义类创建图形窗口界面比较好, 17 不推荐直接使用Frame类来创建图形窗口界面 18 */ 19 class MyFrame extends Frame{ 20 static int id = 0; 21 //定义一个静态成员变量id,用来记录创建出来的窗口的数目 22 MyFrame(int x,int y,int w,int h,Color color){ 23 //自定义构成方法,在构造方法体内使用super调用父类Frame的构造方法 24 super("MyFrame"+(++id)); 25 setBackground(color); 26 /*使用从父类Frame继承而来的方法设置窗体的相关属性*/ 27 setLayout(null); 28 setBounds(x,y,w,h); 29 setVisible(true); 30 } 31 }
运行结果:
2.2.Panel
Panel范例:
1 package cn.javastudy.summary; 2 3 import java.awt.*; 4 public class TestPanel{ 5 public static void main(String args[]){ 6 Frame f = new Frame("JAVA Fram With Panel"); 7 Panel p = new Panel(null); 8 f.setLayout(null); 9 f.setBounds(300,300,500,500);//这里设置的坐标(300,300)是相对于整个屏幕的 10 f.setBackground(new Color(0,0,102));//设置背景颜色时使用三基色(红,绿,蓝)的比例来调配背景色 11 p.setBounds(50,50,400,400);//这里设置的坐标(50,50)是相对于Frame窗体的 12 p.setBackground(new Color(204,204,255)); 13 f.add(p);//把Panel容器装入到Frame容器中,使其能在Frame窗口中显示出来 14 f.setVisible(true); 15 } 16 }
运行结果如下:
三、布局管理器
3.1.第一种布局管理器——FlowLayout
测试代码:
1 package cn.javastudy.summary; 2 3 import java.awt.*; 4 5 public class TestFlowLayout { 6 public static void main(String args[]) { 7 Frame f = new Frame("FlowLayout"); 8 /* 9 * 使用Button类创建按钮 按钮类的其中一个构造方法:Button(String label) label为按钮显示的文本 10 */ 11 Button btn1 = new Button("button1"); 12 Button btn2 = new Button("button2"); 13 Button btn3 = new Button("button3"); 14 /* setLayout方法的定义:public void setLayout(LayoutManager mgr) */ 15 f.setLayout(new FlowLayout());// 使用流水(Flow)线般的布局 16 /* 使用了布局管理器FlowLayout,这里的布局采用默认的水平居中模式 */ 17 // f.setLayout(new FlowLayout(FlowLayout.LEFT)); 18 /* 这里在布局的时候使用了FlowLayout.LEFT常量,这样就将按钮设置为左对齐 */ 19 // f.setLayout(new FlowLayout(FlowLayout.RIGHT)); 20 /* 这里在布局的时候使用了FlowLayout.RIGHT常量,这样就将按钮设置为右对齐 */ 21 f.add(btn1);// 把创建出来的按钮放置到Frame窗体中 22 f.add(btn2); // 这里并没有设置按钮的大小与位置 23 f.add(btn3); // 设置按钮的大小与位置都是由布局管理器来做的 24 f.setVisible(true); 25 f.setSize(200, 200); 26 } 27 }
运行结果如下:
3.2.第二种布局管理器——BorderLayout
测试代码:
1 package cn.javastudy.summary; 2 3 import java.awt.*; 4 5 public class TestBorderLayout { 6 public static void main(String args[]) { 7 Frame f = new Frame("BorderLayout"); 8 Button btnEast = new Button("East"); 9 Button btnWest = new Button("West"); 10 Button btnSouth = new Button("South"); 11 Button btnNorth = new Button("North"); 12 Button btnCenter = new Button("Center"); 13 /* 14 * 把按钮放置到Frame窗体时按照东西南北中五个方向排列好 推荐使用这种方式去排列窗体元素, 15 * 这样容易检查出错误 因为这样写如果写错了编译器会提示出错 16 */ 17 f.add(btnEast, BorderLayout.EAST); 18 f.add(btnWest, BorderLayout.WEST); 19 f.add(btnSouth, BorderLayout.SOUTH); 20 f.add(btnNorth, BorderLayout.NORTH); 21 f.add(btnCenter, BorderLayout.CENTER); 22 /* 23 * 也可以使用这样的方式排列按钮 在把按钮放置到Frame窗体时使用方向定位的字符串指定按钮的放置位置 24 * 这种使用方向定位的字符串指定按钮的放置方式不推荐使用 一旦写错了方向字符串就不好检查出来 25 * 因为即使是写错了仍然可以编译通过 26 */ 27 /* 28 * f.add(btnEast,"East"); 29 * f.add(btnWest,"West"); 30 * f.add(btnSouth,"South"); 31 * f.add(btnNorth,"North"); 32 * f.add(btnCenter,"Center"); 33 */ 34 f.setSize(200, 200); 35 f.setVisible(true); 36 } 37 }
运行结果:
3.3.第三种布局管理器——GridLayout(表格布局管理器)
测试代码:
1 package cn.javastudy.summary; 2 3 import java.awt.*; 4 5 public class TestGridLayout { 6 public static void main(String args[]) { 7 Frame f = new Frame("GridLayout"); 8 Button btn1 = new Button("btn1"); 9 Button btn2 = new Button("btn2"); 10 Button btn3 = new Button("btn3"); 11 Button btn4 = new Button("btn4"); 12 Button btn5 = new Button("btn5"); 13 Button btn6 = new Button("bnt6"); 14 f.setLayout(new GridLayout(3, 2)); 15 /* 把布局划分成3行2列的表格布局形式 */ 16 f.add(btn1); 17 f.add(btn2); 18 f.add(btn3); 19 f.add(btn4); 20 f.add(btn5); 21 f.add(btn6); 22 f.pack(); 23 f.setVisible(true); 24 } 25 }
运行结果:
3.4.布局练习
这几种布局管理器可以设置在Frame里面,也可以设置在Panel里面,而Panel本身也可以加入到Frame里面,因此通过Frame与Panel的嵌套就可以实现比较复杂的布局
实现代码:
1 package cn.javastudy.summary; 2 3 import java.awt.*; 4 public class TestTenButtons{ 5 public static void main(String args[]){ 6 /*这里主要是对显示窗体进行设置*/ 7 Frame f = new Frame("布局管理器的嵌套使用"); 8 f.setLayout(new GridLayout(2,1));//把整个窗体分成2行1列的表格布局 9 f.setLocation(300,400); 10 f.setSize(400,300); 11 f.setVisible(true); 12 f.setBackground(new Color(204,204,255)); 13 /*这里主要是对Panel进行布局的设置*/ 14 Panel p1 = new Panel(new BorderLayout()); 15 Panel p2 = new Panel(new GridLayout(2,1));//p2使用2行1列的表格布局 16 Panel p3 = new Panel(new BorderLayout()); 17 Panel p4 = new Panel(new GridLayout(2,2));//p4使用2行2列的表格布局 18 /*这里主要是把按钮元素加入到Panel里面*/ 19 p1.add(new Button("East(p1-东)"),BorderLayout.EAST); 20 p1.add(new Button("West(p1-西)"),BorderLayout.WEST); 21 p2.add(new Button("p2-Button1")); 22 p2.add(new Button("p2-Button2")); 23 /*p1里面嵌套p2,把p2里面的按钮作为p的中间部分装入到p1里面*/ 24 p1.add(p2,BorderLayout.CENTER);//把p2作为元素加入到p1里面 25 26 p3.add(new Button("East(p3-东)"),BorderLayout.EAST); 27 p3.add(new Button("West(p3-西)"),BorderLayout.WEST); 28 for(int i=0;i<4;i++){ 29 p4.add(new Button("p4-Button"+i)); 30 } 31 /*p3里面嵌套p4,把p4里面的按钮作为p的中间部分装入到p3里面*/ 32 p3.add(p4,BorderLayout.CENTER); 33 34 f.add(p1);//把Panel装入Frame里面,以便于在Frame窗体中显示出来 35 f.add(p3); 36 37 } 38 }
运行结果:
四、布局管理器总结
一、事件监听
测试代码一:
1 package cn.javastudy.summary; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 6 public class TestActionEvent { 7 public static void main(String args[]) { 8 Frame f = new Frame("TestActionEvent"); 9 Button btn = new Button("Press Me"); 10 Monitor m = new Monitor();/* 创建一个监听对象 */ 11 btn.addActionListener(m); 12 /* 13 * 把监听加入到按钮里面,监听按钮的动作, 当按钮触发打击事件时,就会返回一个监听对象e 然后就会自动执行actionPerformed方法 14 */ 15 f.add(btn, BorderLayout.CENTER); 16 f.pack(); 17 addWindowClosingEvent(f); 18 /* 调用这个方法可以自动给Frame窗体里面的子图形元素一个合适的初始大小 */ 19 f.setVisible(true); 20 } 21 22 /** 23 * 点击窗体上的关闭按钮关闭窗体 24 * @param f 25 */ 26 private static void addWindowClosingEvent(Frame f){ 27 f.addWindowListener(new WindowAdapter() { 28 @Override 29 public void windowClosing(WindowEvent arg0) { 30 System.exit(0); 31 } 32 33 }); 34 } 35 } 36 37 /* 38 * 自定义Monitor(监听)类实现事件监听接口ActionListener 一个类要想成为监听类,那么必须实现ActionListener接口 39 */ 40 class Monitor implements ActionListener { 41 /* 重写ActionListener接口里面的actionPerformed(ActionEvent e)方法 */ 42 public void actionPerformed(ActionEvent e) { 43 System.out.println("A Button has been Pressed"); 44 } 45 }
测试代码二:
1 package cn.javastudy.summary; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 public class TestActionEvent2{ 6 public static void main(String args[]){ 7 Frame f = new Frame("TestActionEvent"); 8 Button btn1 = new Button("start"); 9 Button btn2 = new Button("stop"); 10 Monitor2 m2 = new Monitor2();//创建监听对象 11 btn1.addActionListener(m2); 12 /*一个监听对象同时监听两个按钮的动作*/ 13 btn2.addActionListener(m2); 14 btn2.setActionCommand("GameOver");//设置btn2的执行单击命令后的返回信息 15 f.add(btn1,BorderLayout.NORTH); 16 f.add(btn2,BorderLayout.CENTER); 17 18 f.pack(); 19 f.setVisible(true); 20 } 21 } 22 23 class Monitor2 implements ActionListener{ 24 public void actionPerformed(ActionEvent e){ 25 System.out.println("a button has been pressed,"+"the relative info is:\n"+e.getActionCommand()); 26 /*使用返回的监听对象e调用getActionCommand()方法获取两个按钮执行单击命令后的返回信息 27 根据返回信息的不同区分开当前操作的是哪一个按钮,btn1没有使用setActionCommand()方法设置 28 则btn1返回的信息就是按钮上显示的文本*/ 29 } 30 }
二、TextField事件监听
测试代码:
1 package cn.javastudy.summary; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 6 public class TestTextField { 7 public static void main(String args[]) { 8 new MyFrameTextField(); 9 } 10 } 11 12 class MyFrameTextField extends Frame { 13 MyFrameTextField() { 14 TextField tf = new TextField(); 15 add(tf); 16 tf.addActionListener(new Monitor3()); 17 tf.setEchoChar('*'); 18 /* 19 * 这个setEchoChar()方法是设置文本框输入时显示的字符,这里设置为*, 20 * 这样输入任何内容就都以*显示出来,不过打印出来时依然可以看到输入的内容 21 */ 22 setVisible(true); 23 pack(); 24 } 25 } 26 27 class Monitor3 implements ActionListener { 28 /* 29 * 接口里面的所有方法都是public(公共的) 30 * 所以从API文档复制void actionPerformed(ActionEvent e)时 要在void前面加上public 31 */ 32 public void actionPerformed(ActionEvent e) { 33 /* 事件的相关信息都封装在了对象e里面,通过对象e的相关方法就可以获取事件的相关信息 */ 34 TextField tf = (TextField) e.getSource(); 35 /* 36 * getSource()方法是拿到事件源,注意:拿到这个事件源的时候, 37 * 是把它当作TextField的父类来对待 38 * getSource()方法的定义是:“public Object getSource()”返回值是一个Object对象, 39 * 所以要强制转换成TextField类型的对象 40 * 在一个类里面想访问另外一个类的事件源对象可以通过getSource()方法 41 */ 42 System.out.println(tf.getText());// tf.getText()是取得文本框里面的内容 43 tf.setText("");// 把文本框里面的内容清空 44 } 45 }
使用TextField类实现简单的计算器
1 package cn.javastudy.summary; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 6 public class TestMath { 7 public static void main(String args[]) { 8 new TFFrame(); 9 } 10 } 11 12 /* 这里主要是完成计算器元素的布局 */ 13 class TFFrame extends Frame { 14 TFFrame() { 15 /* 16 * 创建3个文本框,并指定其初始大小分别为10个字符和15个字符的大小 这里使用的是TextField类的另外一种构造方法 public TextField(int columns) 17 */ 18 TextField num1 = new TextField(10); 19 TextField num2 = new TextField(10); 20 TextField num3 = new TextField(15); 21 /* 创建等号按钮 */ 22 Button btnEqual = new Button("="); 23 btnEqual.addActionListener(new MyMonitor(num1, num2, num3)); 24 /* 给等号按钮加上监听,让点击按钮后有响应事件发生 */ 25 Label lblPlus = new Label("+"); 26 /* “+”是一个静态文本,所以使用Label类创建一个静态文本对象 */ 27 setLayout(new FlowLayout()); 28 /* 把Frame默认的BorderLayout布局改成FlowLayout布局 */ 29 add(num1); 30 add(lblPlus); 31 add(num2); 32 add(btnEqual); 33 add(num3); 34 pack(); 35 setVisible(true); 36 37 } 38 } 39 40 class MyMonitor implements ActionListener { 41 TextField num1, num2, num3; 42 43 /* 44 * 为了使对按钮的监听能够对文本框也起作用, 45 * 所以在自定义类MyMonitor里面定义三个TextField类型的对象 num1,num2,num3, 46 * 并且定义了MyMonitor类的一个构造方法 这个构造方法带有三个TextField类型的参数, 47 * 用于接收 从TFFrame类里面传递过来的三个TextField类型的参数 48 * 然后把接收到的三个TextField类型的参数赋值给在本类中声明的 三个TextField类型的参数num1,num2,num3 然后再在actionPerformed()方法里面处理num1,num2,num3 49 */ 50 public MyMonitor(TextField num1, TextField num2, TextField num3) { 51 this.num1 = num1; 52 this.num2 = num2; 53 this.num3 = num3; 54 } 55 56 public void actionPerformed(ActionEvent e) { 57 /* 事件的相关信息都封装在了对象e里面,通过对象e的相关方法就可以获取事件的相关信息 */ 58 int n1 = Integer.parseInt(num1.getText());/* num1对象调用getText()方法取得自己显示的文本字符串 */ 59 int n2 = Integer.parseInt(num2.getText());/* num2对象调用getText()方法取得自己显示的文本字符串 */ 60 num3.setText("" + (n1 + n2));/* num3对象调用setText()方法设置自己的显示文本 */ 61 num1.setText(""); 62 /* 计算结束后清空num1,num2文本框里面的内容 */ 63 num2.setText(""); 64 // num3.setText(String.valueOf((n1+n2))); 65 /* 字符串与任意类型的数据使用“+”连接时得到的一定是字符串, 66 * 这里使用一个空字符串与int类型的数连接,这样就可以直接把(n1+n2)得到的int类型的数隐式地转换成字符串了, 67 * 这是一种把别的基础数据类型转换成字符串的一个小技巧。 68 * 也可以使用“String.valueOf((n1+n2))”把(n1+n2)的和转换成字符串 69 */ 70 } 71 }
JAVA里面的经典用法:在一个类里面持有另外一个类的引用
1 package cn.javastudy.summary; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 6 public class TestMath1 { 7 public static void main(String args[]) { 8 new TTMyFrame().launchFrame(); 9 /* 创建出TTMyFrame对象后调用lauchFrame()方法把计算器窗体显示出来 */ 10 } 11 } 12 13 /* 做好计算器的窗体界面 */ 14 class TTMyFrame extends Frame { 15 /* 把设计计算器窗体的代码封装成一个方法 */ 16 TextField num1, num2, num3; 17 18 public void launchFrame() { 19 num1 = new TextField(10); 20 num2 = new TextField(15); 21 num3 = new TextField(15); 22 Label lblPlus = new Label("+"); 23 Button btnEqual = new Button("="); 24 btnEqual.addActionListener(new MyMonitorbtnEqual(this)); 25 setLayout(new FlowLayout()); 26 add(num1); 27 add(lblPlus); 28 add(num2); 29 add(btnEqual); 30 add(num3); 31 pack(); 32 setVisible(true); 33 } 34 } 35 36 /* 37 * 这里通过取得TTMyFrame类的引用,然后使用这个引用去访问TTMyFrame类里面的成员变量 38 * 这种做法比上一种直接去访问TTMyFrame类里面的成员变量要好得多, 39 * 因为现在不需要知道 TTMyFrame类里面有哪些成员变量了, 40 * 现在要访问TTMyFrame类里面的成员变量,直接使用 TTMyFrame类对象的引用去访问即可, 41 * 这个TTMyFrame类的对象好比是一个大管家, 而我告诉大管家,我要访问TTMyFrame类里面的那些成员变量, 42 * 大管家的引用就会去帮我找,不再需要我自己去找了。 43 * 这种在一个类里面持有另一个类的引用的用法是一种非常典型的用法 44 * 使用获取到的引用就可以在一个类里面访问另一个类的所有成员了 45 */ 46 class MyMonitorbtnEqual implements ActionListener { 47 TTMyFrame ttmf = null; 48 49 public MyMonitorbtnEqual(TTMyFrame ttmf) { 50 this.ttmf = ttmf; 51 } 52 53 public void actionPerformed(ActionEvent e) { 54 int n1 = Integer.parseInt(ttmf.num1.getText()); 55 int n2 = Integer.parseInt(ttmf.num2.getText()); 56 ttmf.num3.setText("" + (n1 + n2)); 57 ttmf.num1.setText(""); 58 ttmf.num2.setText(""); 59 } 60 }
运行结果如下:
三、内部类
内部类的使用范例:
1 package cn.javastudy.summary; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 6 public class TestMath3 { 7 8 public static void main(String args[]) { 9 new MyMathFrame().launchFrame(); 10 } 11 } 12 13 class MyMathFrame extends Frame { 14 TextField num1, num2, num3; 15 16 public void launchFrame() { 17 num1 = new TextField(10); 18 num2 = new TextField(15); 19 num3 = new TextField(15); 20 Label lblPlus = new Label("+"); 21 Button btnEqual = new Button("="); 22 btnEqual.addActionListener(new MyMonitor()); 23 setLayout(new FlowLayout()); 24 add(num1); 25 add(lblPlus); 26 add(num2); 27 add(btnEqual); 28 add(num3); 29 pack(); 30 setVisible(true); 31 } 32 33 /* 34 * 这个MyMonitor类是内部类,它在MyFrame类里面定义 MyFrame类称为MyMonitor类的包装类 35 */ 36 /* 37 * 使用内部类的好处: 38 * 第一个巨大的好处就是可以畅通无阻地访问外部类(即内部类的包装类)的所有成员变量和方法 39 * 如这里的在MyFrame类(外部类)定义的三个成员变量num1,num2,num3, 40 * 在MyMonitor(内部类)里面就可以直接访问 41 * 这相当于在创建外部类对象时内部类对象默认就拥有了一个外部类对象的引用 42 */ 43 private class MyMonitor implements ActionListener { 44 public void actionPerformed(ActionEvent e) { 45 int n1 = Integer.parseInt(num1.getText()); 46 int n2 = Integer.parseInt(num2.getText()); 47 num3.setText("" + (n1 + n2)); 48 num1.setText(""); 49 num2.setText(""); 50 } 51 } 52 }
内部类带来的巨大好处是:
- 可以很方便地访问外部类定义的成员变量和方法
- 当某一个类不需要其他类访问的时候就把这个类声明为内部类。
四、Graphics 类
测试代码:
1 package cn.javastudy.summary; 2 3 import java.awt.*; 4 public class TestPaint{ 5 public static void main(String args[]){ 6 new MyPaint().launchFrame(); 7 /*在main()方法里面并没有显示调用paint(Graphics g)方法 8 可是当创建出Frame窗体后却可以看到Frame窗体上画出了 9 圆和矩形,这是因为paint()方法是一个比较特殊的方法 10 在创建Frame窗体时会自动隐式调用 11 当我们把Frame窗体最小化又再次打开时,又会再次调用 12 paint()方法重新把圆和矩形在Frame窗体上画出来 13 即每次需要重画Frame窗体的时候就会自动调用paint()方法*/ 14 } 15 } 16 17 class MyPaint extends Frame{ 18 public void launchFrame(){ 19 setBounds(200,200,640,480); 20 setVisible(true); 21 } 22 23 public void paint(Graphics g){ 24 /*paint(Graphics g)方法有一个Graphics类型的参数g 25 我们可以把这个g当作是一个画家,这个画家手里拿着一只画笔 26 我们通过设置画笔的颜色与形状来画出我们想要的各种各样的图像*/ 27 /*设置画笔的颜色*/ 28 g.setColor(Color.red); 29 g.fillOval(100,100,100,100);/*画一个实心椭圆*/ 30 g.setColor(Color.green); 31 g.fillRect(150,200,200,200);/*画一个实心矩形*/ 32 /*这下面的两行代码是为了写程序的良好编程习惯而写的 33 前面设置了画笔的颜色,现在就应该把画笔的初始颜色恢复过来 34 就相当于是画家用完画笔之后把画笔上的颜色清理掉一样*/ 35 Color c = g.getColor(); 36 g.setColor(c); 37 } 38 }
运行结果:
五、鼠标事件适配器
测试代码:
1 package cn.galc.test; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import java.util.*; 6 public class MyMouseAdapter{ 7 public static void main(String args[]) { 8 new MyFrame("drawing..."); 9 } 10 } 11 12 class MyFrame extends Frame { 13 ArrayList points = null; 14 MyFrame(String s) { 15 super(s); 16 points = new ArrayList(); 17 setLayout(null); 18 setBounds(300,300,400,300); 19 this.setBackground(new Color(204,204,255)); 20 setVisible(true); 21 this.addMouseListener(new Monitor()); 22 } 23 24 public void paint(Graphics g) { 25 Iterator i = points.iterator(); 26 while(i.hasNext()){ 27 Point p = (Point)i.next(); 28 g.setColor(Color.BLUE); 29 g.fillOval(p.x,p.y,10,10); 30 31 } 32 } 33 34 public void addPoint(Point p){ 35 points.add(p); 36 } 37 } 38 39 class Monitor extends MouseAdapter { 40 public void mousePressed(MouseEvent e) { 41 MyFrame f = (MyFrame)e.getSource(); 42 f.addPoint(new Point(e.getX(),e.getY())); 43 f.repaint(); 44 } 45 }
六、window事件
测试代码:
1 package cn.galc.test; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 public class TestWindowClose{ 6 public static void main(String args[]){ 7 new WindowFrame("关闭WindowFrame"); 8 } 9 } 10 11 class WindowFrame extends Frame{ 12 public WindowFrame(String s){ 13 super(s); 14 setBounds(200,200,400,300); 15 setLayout(null); 16 setBackground(new Color(204,204,255)); 17 setVisible(true); 18 this.addWindowListener(new WindowMonitor()); 19 /*监听本窗体的动作,把所有的动作信息封装成一个对象传递到监听类里面*/ 20 21 this.addWindowListener( 22 /*在一个方法里面定义一个类,这个类称为局部类,也叫匿名的内部类, 23 这里的{……代码……}里面的代码很像一个类的类体,只不过这个类没有名字,所以叫匿名类 24 在这里是把这个匿名类当成WindowAdapter类来使用,语法上这样写的本质意义是相当于这个匿名类 25 从WindowAdapter类继承,现在new了一个匿名类的对象出来然后把这个对象当成WindowAdapter来使用 26 这个匿名类出了()就没有人认识了*/ 27 new WindowAdapter(){ 28 public void windowClosing(WindowEvent e){ 29 setVisible(false); 30 System.exit(-1); 31 } 32 } 33 ); 34 } 35 36 /*这里也是将监听类定义为内部类*/ 37 class WindowMonitor extends WindowAdapter{ 38 /*WindowAdapter(Window适配器)类实现了WindowListener监听接口 39 重写了WindowListener接口里面的所有方法 40 如果直接使用自定义WindowMonitor类直接去 41 实现WindowListener接口,那么就得要重写WindowListener接口 42 里面的所有方法,但现在只需要用到这些方法里面的其中一个方法 43 所以采用继承实现WindowListener监听接口的一个子类 44 并重写这个子类里面需要用到的那个方法即可 45 这种做法比直接实现WindowListener监听接口要重写很多个用不到的方法要简洁方便得多*/ 46 /*重写需要用到的windowClosing(WindowEvent e)方法*/ 47 public void windowClosing(WindowEvent e){ 48 setVisible(false);/*将窗体设置为不显示,即可实现窗体关闭*/ 49 System.exit(0);/*正常退出*/ 50 } 51 } 52 }
七、键盘响应事件——KeyEvent
测试代码:
1 package cn.galc.test; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 public class TestKeyEvent{ 6 public static void main(String args[]){ 7 new KeyFrame("键盘响应事件"); 8 } 9 } 10 11 class KeyFrame extends Frame{ 12 public KeyFrame(String s){ 13 super(s); 14 setBounds(200,200,400,300); 15 setLayout(null); 16 setVisible(true); 17 addKeyListener(new KeyMonitor()); 18 } 19 /*把自定义的键盘的监听类定义为内部类 20 这个监听类从键盘适配器KeyAdapter类继承 21 从KeyAdapter类继承也是为了可以简洁方便 22 只需要重写需要用到的方法即可,这种做法比 23 直接实现KeyListener接口要简单方便,如果 24 直接实现KeyListener接口就要把KeyListener 25 接口里面的所有方法重写一遍,但真正用到的 26 只有一个方法,这样重写其他的方法但又用不到 27 难免会做无用功*/ 28 class KeyMonitor extends KeyAdapter{ 29 public void keyPressed(KeyEvent e){ 30 int keycode = e.getKeyCode(); 31 /*使用getKeyCode()方法获取按键的虚拟码*/ 32 /*如果获取到的键的虚拟码等于up键的虚拟码 33 则表示当前按下的键是up键 34 KeyEvent.VK_UP表示取得up键的虚拟码 35 键盘中的每一个键都对应有一个虚拟码 36 这些虚拟码在KeyEvent类里面都被定义为静态常量 37 所以可以使用“类名.静态常量名”的形式访问得到这些静态常量*/ 38 if(keycode == KeyEvent.VK_UP){ 39 System.out.println("你按的是up键"); 40 } 41 } 42 } 43 } 44 /*键盘的处理事件是这样的:每一个键都对应着一个虚拟的码, 45 当按下某一个键时,系统就会去找这个键对应的虚拟的码,以此来确定当前按下的是那个键 46 */