三个概念:组件(component) 容器(Container) 布局管理器(LayoutManager)
关系: 容器中放置组件,组件的排列方式可以通过布局管理器设置。
用户设置布局管理器后,setLocation()等方法会被布局管理器覆盖;用户想亲自设置组件大小和位置,应取消容器的布局管理器
setLayout(null);
有三种类型的容器:Window,Panel,ScrollPane
常用的有Frame,Panel,Applet
1. Frame
生成一个窗口,一般不用Window, 而是用其子类Frame。
实例化后,Frame是不可见且无大小。故需调用setSize() setVisible(true)
1 import java.awt.*; 2 3 public class MyFrame extends Frame { 4 public static void main(String args[]) { 5 MyFrame fr = new MyFrame("Hello Out There!"); 6 7 fr.setSize(200, 200); // 设置Frame的大小, 缺省为(0 ,0) 8 fr.setBackground(Color.red); // 设置Frame的背景,缺省为红色 9 fr.setVisible(true); // 设置Frame为可见,缺省为不可见 10 } 11 12 public MyFrame(String str) { 13 super(str); // 调用父类的构造方法 14 } 15 }
2. Panel
eg: 带有Panel的Frame
1 import java.awt.*; 2 3 public class FrameWithPanel extends Frame { 4 public FrameWithPanel(String str) { 5 super(str); 6 } 7 8 public static void main(String args[]) { 9 FrameWithPanel fr = new FrameWithPanel("Frame with pannel"); 10 Panel pan = new Panel(); 11 fr.setSize(200, 200); 12 fr.setBackground(Color.red); 13 14 fr.setLayout(null); // 取消布局管理器 15 16 pan.setSize(100, 100); 17 pan.setBackground(Color.yellow); // 设置面板pan的背景颜色为黄色 18 19 fr.add(pan); // 用add方法把pan面板添加到框架fr中 20 21 fr.setVisible(true); 22 } 23 }
3. LayoutManger布局管理器
组件的排列顺序、组件的大小、位置、当窗口移动或调整大小后组件如何变化可授权给布局管理器来管理。
不同的布局管理器其算法和策略不同。
FlowLayout
Panel和Applet的缺省布局管理器。
其规律为从上到下,从左到右放置。
容器发生变化时,组件大小不变,相对位置改变。
构造方法:
FlowLayout(FlowLayout.RIGHT, 20, 40); // 右对齐,横向间隔20,纵向间隔40
FlowLayout(FlowLayout.LEFT); // 左对齐,横向间隔、纵向间隔缺省:5
FlowLayout(); // 居中对齐,横向间隔、纵向间隔缺省:5
eg. Frame采用FlowLayout()
1 import java.awt.*; 2 3 public class myButtons { 4 public static void main(String args[]) { 5 Frame f = new Frame(); 6 f.setLayout(new FlowLayout()); 7 Button button1 = new Button("OK"); 8 Button button2 = new Button("Open"); 9 Button button3 = new Button("Close"); 10 f.add(button1); 11 f.add(button2); 12 f.add(button3); 13 14 f.setSize(300, 100); 15 f.setVisible(true); 16 }
BorderLayout
Window, Frame和Dialog的缺省布局管理器
有5个区域:North South East West Center
容器发生变化时,组件相对位置不变,组件大小改变
eg. Frame采用BorderLayout
1 import java.awt.*; 2 3 public class buttonDir { 4 public static void main(String args[]) { 5 Frame f = new Frame("BorderLayout"); 6 f.setLayout(new BorderLayout()); 7 f.add("North", new Button("North")); 8 f.add("South", new Button("South")); 9 f.add("East", new Button("East")); 10 f.add("West", new Button("West")); 11 f.add("Center", new Button("Center")); 12 13 f.setSize(200, 200); 14 f.setVisible(true); 15 } 16 }
GridLayout
容器中各个组件呈网格状布局,平均占据容器的空间
eg. GridLayout生成3行2列的布局。
1 import java.awt.*; 2 3 public class ButtonGrid { 4 public static void main(String args[]) { 5 Frame f = new Frame("GridLayout"); 6 f.setLayout(new GridLayout(3, 2)); // 容器平均分成3行2列 7 f.add(new Button("1")); // 第一行第一格 8 f.add(new Button("2")); // 第一行下一格 9 f.add(new Button("3")); // 第二行第一格 10 f.add(new Button("4")); // 第二行下一格 11 f.add(new Button("5")); // 第三行第一格 12 f.add(new Button("6")); // 第三行下一格 13 f.setSize(200, 200); 14 f.setVisible(true); 15 } 16 }
CardLayout
两个或以上的成员共享同一显示空间,分成多层,每层只允许放置一个组件,可通过panel实现复杂界面。
1 import java.awt.*; 2 import java.awt.event.*; 3 4 public class ThreePages implements MouseListener { 5 CardLayout layout = new CardLayout(); // 初始化一个牌局管理器对象 6 Frame f = new Frame("CardLayout"); 7 Button page1Button; 8 Label page2Label; 9 TextArea page3Text; // 多行多列的文本区域 10 Button page3Top; 11 Button Page3Button; 12 13 public static void main(String args[]) { 14 new ThreePages.go(); 15 } 16 17 public void go() { 18 f.setLayout(layout); 19 f.add(page1Button = new Button("Button page"), "page1Button"); 20 // 第二个参数表示对这层牌所取的名字 21 page1Button.addMouseListener(this); // 注册监听器 22 23 f.add(page2Label = new Label("Label page"), "page2Label"); 24 page2Label.addMouseListner(this); 25 26 Panel panel = new Panel(); 27 panel.setLayout(new BorderLayout()); 28 panel.add(page3Text = new TextArea("Composite page"), "Center"); 29 page3Text.addMouseListner(this); 30 panel.add(page3Top = new Button("Top button"), "North"); 31 page3Top.addMouseListner(this); 32 panel.add(Page3Button = new Button("Bottom button"), "South"); 33 page3Button.addMouseListner(this); 34 f.add(panel, "panel"); 35 36 f.setSize(200, 200); 37 f.setVisible(true); 38 39 40 } 41 }
事件
步骤:1. 编写监听器类。对于某类事件XXXEvent, 事件源想要接受并处理,需定义相应的监听器类,该类需继承该事件相应接口XXXListener
2. 授权。事件源注册该类事件的监听器,使用addXXXListener(XXXLisetner)方法来注册监听器。
eg. button注册Action事件
1 import java.awt.*; 2 import java.awt.event.*; 3 4 public class TestButton { 5 public static void main(String args[]) { 6 Frame f = new Frame("Test"); 7 Button b = new Button("Press Me!"); 8 b.addActionListener(new ButtonHandler()); 9 f.setLayout(new FlowLayout()); 10 f.add(b); 11 f.setSize(200, 200); 12 f.setVisible(true); 13 } 14 } 15 16 class ButtonHandler implements ActionListener { 17 public void actionPerformed(ActionEvent e) { 18 System.out.println("Action occurred"); 19 } 20 }
AWT共有10类事件,分为两类:低级事件和高级事件
低级事件:基于容器和组件
ComponentEvent:组件事件,组件的尺寸变化、移动
ContainerEvent:组件增加、移动
WindowEvent: 窗口事件,关闭窗口,窗口闭合,图标化
FocusEvent:焦点事件,焦点的获得和丢失
KeyEvent:键盘事件,键按下、释放
MouseEvent:鼠标事件,鼠标单击、移动
高级事件:基于语义
ActionEvent:动作事件,按钮按下,TextField中按Enter键
AdjustmentEvent: 调节事件,在滚动条上移动滑块以调节数值
ItemEvent:项目事件,选择项目
TextEvent: 文本事件,文本对象改变
eg. 实现3个监听器事件接口
1 import java.awt.*; 2 import java.awt.event.*; 3 4 public class ThreeListener implements MouseMotionListener, MouseListener, 5 WindowListener { 6 private Frame f; 7 private TextField tf; 8 9 public static void main(String args[]) { 10 ThreeListener two = new ThreeListener(); 11 two.go(); 12 } 13 14 public void go() { 15 f = new Frame("Three listner example"); 16 f.add(new Label("Click and Drag the mouse"), "North"); 17 tf = new TextField(30); 18 f.add(tf, "South"); 19 20 f.addMouseMotionListener(this); 21 f.addMouseListener(this); 22 f.addWindowListener(this); 23 24 f.setSize(300, 200); 25 f.setVisible(true); 26 } 27 // MouseMotionListener接口的实现 28 public void mouseDragged(MouseEvent e) { 29 String s = "Mousedragging: X=" + e.getX() + "Y=" + e.getY(); 30 tf.setText(s); 31 } 32 33 public void mouseMoved(MouseEvent e) { 34 } 35 36 // MouseListener接口的实现 37 public void mouseClicked(MouseEvent e) { 38 } 39 // 鼠标进入时 40 public void mouseEntered(MouseEvent e) { 41 String s = "the Mouse Entered"; 42 tf.setText(s); 43 } 44 // 鼠标离开时 45 public void mouseExited(MouseEvent e) { 46 String s = "the mouse has left the building"; 47 tf.setText(s); 48 } 49 50 public void mousePressed(MouseEvent e) { 51 } 52 53 public void mouseReleased(MouseEvent e) { 54 } 55 56 // WindowListener接口的实现 57 public void windowOpened(WindowEvent e) { 58 } 59 60 public void windowClosed(WindowEvent e) { 61 } 62 63 public void windowClosing(WindowEvent e) { 64 System.exit(1); 65 } 66 67 public void windowActivated(WindowEvent e) { 68 } 69 70 public void windowDeactivated(WindowEvent e) { 71 } 72 73 public void windowIconified(WindowEvent e) { 74 } 75 76 public void windowDeiconified(WindowEvent e) { 77 } 78 }
事件适配器
从以上的例子看出,要实现一个监听器类,当继承相应的接口时,就要实现其所有的方法,尽管很多时候你并不对所有方法都感兴趣。Java提供了一些现有的父类,只要继承就可以,重写需要方法,无关方法不用实现。
java.awt.event包中定义的事件适配器类包括以下几个:
ComponentAdapter(组件适配器)
ContainerAdapter(容器适配器)
FocuAdapter(焦点适配器)
KeyAdapter(键盘适配器)
MouseAdapter(鼠标适配器)
MouseMotionAdapter(鼠标运动适配器)
WindowAdapter(窗口适配器)
有两种方法使用适配器
使用内部类:内部类可以调用外部类的成员方法和变量,包括私有的成员
1 import java.awt.*; 2 import java.awt.event.*; 3 4 public class InnerClass { 5 private Frame f; 6 private TextField tf; 7 8 public InnerClass() { 9 f = new Frame("Inner classes example"); 10 tf = new TextField(30); 11 } 12 13 public void launchFrame() { 14 Label label = new Label("Click and drog the mouse"); 15 f.add(label, "North"); 16 f.add(tf, "South"); 17 f.addMouseMotionListener(new MyMouseMotionListener()); 18 f.setSize(300, 200); 19 f.setVisible(true); 20 } 21 22 class MyMouseMotionListener extends MouseMotionAdapter { 23 // 内部类继承MouseMotionAdapter适配器 24 public void mouseDragged(MouseEvent e) { 25 String s = "Mouse dragging: x=" + e.getX() + "Y=" + e.getY(); 26 tf.setText(s); 27 } 28 } 29 30 public static void main(String args[]) { 31 InnerClass obj = new InnerClass(); 32 obj.launchFrame(); 33 } 34 }
使用匿名类:也就是此类没有名字。当一个内部类的类声明只是在创建对象时用到,且必须有父类或实现一个接口,才能用匿名类。
它只是显示的调用一个无参的父类的构造方法。
1 import java.awt.*; 2 import java.awt.event.*; 3 4 public class AnonymousClass { 5 private Frame f; 6 private TextField tf; 7 8 public AnonymousClass() { 9 f = new Frame("Inner classes example"); 10 tf = new TextField(30); 11 } 12 13 public void launchFrame() { 14 Label label = new Label("Click and drog the mouse"); 15 f.add(label, "North"); 16 f.add(tf, "South"); 17 f.addMouseMotionListener(new MouseMotionAdapter() { // 无参的父类构造函数,匿名类 18 public void mouseDragged(MouseEvent e) { 19 String s = "Mouse dragging: x=" + e.getX() + "Y=" + e.getY(); 20 tf.setText(s); 21 } 22 }); 23 f.setSize(300, 200); 24 f.setVisible(true); 25 } 26 27 28 public static void main(String args[]) { 29 AnonymousClass obj = new AnonymousClass(); 30 obj.launchFrame(); 31 } 32 }
几个组件
按钮(Button)
被点击后,产生ActionEvent事件,需ActionListener接口进行监听。
ActionEvent的对象调用getActionCommand()方法可得到按钮的标识名
setActionCommand()可以为按钮设置组件标示符
复选框(CheckBox)
提供简单的“on/off”开关,旁边显示文本标签
构造方法如下:
setLayout(new GridLayout(3, 1));
add(new CheckBox("one", null, true));
add(new CheckBox("two"));
add(new CheckBox("Three"));
用ItemListner来监听ItemEvent事件
用getStateChange()获取当前状态
用getItem()获得被修改复选框的字符串对象
复选框组
下拉式菜单(Choice)
Choice Colorchooser = new Choice();
Colorchooser.add("Green");
Colorchooser.add("Red");
Choice用ItemListener接口来进行监听
画布(Canvas)
要继承Canvas类才能获得有用的功能
完成图形处理,需重写paint()方法
监听各种鼠标、键盘事件(即可以注册对应的监听器)
在Canvas组件中输入字符,需先调用requestFocus()方法
1 import java.awt.*; 2 import java.awt.event.*; 3 import java.util.*; 4 5 public class MyCanvas implements KeyListener, MouseListener { 6 Canvas c; 7 String s = ""; 8 9 public static void main(String args[]) { 10 Frame f = new Frame("Canvas"); 11 12 MyCanvas mc = new MyCanvas(); 13 mc.c = new Canvas(); 14 15 f.add(mc.c, "Center"); 16 17 mc.c.addMouseListener(mc); 18 mc.c.addKeyListener(mc); 19 f.addWindowListener(new WindowAdapter() { 20 public void windowClosing(WindowEvent e) { 21 System.exit(1); 22 } 23 }); 24 // 匿名类Adapter 25 26 f.setSize(150, 150); 27 f.setVisible(true); 28 } 29 30 // 实现MouseListener接口 31 public void mouseClicked(MouseEvent e) { 32 System.out.println("Mouse Clicked"); 33 c.requestFocus(); // 鼠标点击后获得聚焦 34 } 35 36 public void mouseEntered(MouseEvent e) { 37 System.out.println("Mouse Entered"); 38 } 39 40 public void mouseExited(MouseEvent e) { 41 System.out.println("Mouse Exited"); 42 } 43 44 public void mousePressed(MouseEvent e) { 45 System.out.println("Mouse Pressed"); 46 } 47 48 public void mouseReleased(MouseEvent e) { 49 System.out.println("Mouse Released"); 50 } 51 52 // 实现KeyListener接口 53 public void keyPressed(KeyEvent e) { 54 System.out.println("Key Pressed"); 55 } 56 57 public void keyReleased(KeyEvent e) { 58 System.out.println("Key Releaseed"); 59 } 60 61 public void keyTyped(KeyEvent e) { 62 System.out.println("KeyTyped"); 63 s += e.getKeyChar(); // 获取每个输入的字符,添加到s 64 c.getGraphics().drawString(s, 0, 20); //显示s 65 } 66 67 }