三個概念:組件(component) 容器(Container) 布局管理器(LayoutManager)
關系: 容器中放置組件,組件的排列方式可以通過布局管理器設置。
用戶設置布局管理器后,setLocation()等方法會被布局管理器覆蓋;用戶想親自設置組件大小和位置,應取消容器的布局管理器
setLayout(null);
有三種類型的容器:Window,Panel,ScrollPane
常用的有Frame,Panel,Applet
1. Frame
生成一個窗口,一般不用Window, 而是用其子類Frame。
實例化后,Frame是不可見且無大小。故需調用setSize() setVisible(true)
View Code
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
View Code
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()
View Code
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
View Code
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列的布局。
View Code
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實現復雜界面。
View Code
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事件
View Code
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個監聽器事件接口
View Code
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(窗口適配器)
有兩種方法使用適配器
使用內部類:內部類可以調用外部類的成員方法和變量,包括私有的成員
View Code
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 }
使用匿名類:也就是此類沒有名字。當一個內部類的類聲明只是在創建對象時用到,且必須有父類或實現一個接口,才能用匿名類。
它只是顯示的調用一個無參的父類的構造方法。
View Code
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()方法
View Code
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 }
