• 1. 《Java程序设计之网络编程》 计算机学院 电子邮件:lizhx@126.com 教学课件
  • 2. 第11章 GUI程序设计
  • 3. 主要内容11.1 AWT组件简介 11.2布局管理器 11.3 AWT事件处理 11.4 常用AWT组件使用举例 11.5 Swing组件设计用户界面 11.6 AWT图形和Java2D图形
  • 4. 11.1 AWT组件简介11.1.1 Frame框架类 11.1.3 Panel面板类
  • 5. 例子
  • 6. AWT介绍抽象窗口工具包AWT (Abstract Window Toolkit) 是 API为Java 程序提供的建立图形用户界面GUI (Graphics User Interface)工具集,AWT可用于Java的applet和applications中。它支持图形用户界面编程的功能包括: 用户界面组件;事件处理模型;图形和图像工具,包括形状、颜色和字体类;布局管理器,可以进行灵活的窗口布局而与特定窗口的尺寸和屏幕分辨率无关;数据传送类,可以通过本地平台的剪贴板来进行剪切和粘贴。 (其他类似的有Swing,SWT)
  • 7. java.awt包     java.awt包中提供了GUI设计所使用的类和接口,可从下图中看到主要类之间的关系。   java.awt包提供了基本的java程序的GUI设计工具。主要包括下述三个概念:   组件--Component   容器--Container   布局管理器--LayoutManager  
  • 8. AWT包包含的主要类
  • 9. 容器java.awt.Container是Component的子类,一个容器可以容纳多个组件,并使它们成为一个整体。容器可以简化图形化界面的设计,以整体结构来布置界面。所有的容器都可以通过add()方法向容器中添加组件。   有三种类型的容器:Window、Panel、ScrollPane,常用的有Panel, Frame, Applet。
  • 10. 11.1.1 Frame框架类一般我们要生成一个窗口,通常是用Window的子类Frame来进行实例化,而不直接用到Window类。Frame的外观就像我们平常在windows系统下见到的窗口,有标题、边框、菜单、大小等等。每个Frame的对象实例化以后,默认是不显示和最小化的,因此必须调用setSize()来设置大小,调用setVisible(true)来设置该窗口为可见的。框架类的许多方法都是从它的超类Window类及更上层的Container和Component类继承而来。
  • 11. (本页无文本内容)
  • 12. Frame的例子import java.awt.*;   public class MyFrame extends Frame{   public static void main(String args[ ]){     MyFrame fr = new MyFrame(“Hello Out There!”);                        //构造方法     fr.setSize(200,200);             //设置Frame的大小,缺省为(0,0)         fr.setBackground(Color.red);             //设置Frame的背景,缺省为红色     fr.setVisible(true);              //设置Frame为可见,缺省为不可见    }       public MyFrame (String str){         super(str); //调用父类的构造方法      }   }
  • 13. 11.1.3 Panel面板类 Panel是一种没有标题的容器。并且实例化后必须用Container的add方法加入到Window对象中。 java应用程序中,一般独立应用程序主要使用框架做容器,在Frame上通过放置Panel面板来控制图形界面的布局。如果应用到浏览器中,则主要使用Panel的一个子类Applet来做容器。Applet是一个能够嵌入浏览器运行的特殊容器。
  • 14. (本页无文本内容)
  • 15. 例子:Frame with PannelPannel的子类Applet
  • 16. import java.awt.*; public class FrameWithPanel extends Frame{ public FrameWithPanel(String str){         super(str);   } public static void main(String args[]){ FrameWithPanel fr = new FrameWithPanel("Frame with Panel"); Panel pan=new Panel();  fr.setSize(200,200);  fr.setBackground(Color.red);        //框架fr的背景颜色设置为红色  fr.setLayout(null);                //取消布局管理器  pan.setSize(100,100);  pan.setBackground(Color.yellow);           //设置面板pan的背景颜色为黄色  fr.add(pan); //用add方法把面板pan添加到框架fr中  fr.setVisible(true);    }  }
  • 17. 11.1.1 Frame框架类AWT在实际的运行过程中是调用所在平台的图形系统,因此同样一段AWT程序在不同的操作系统平台下运行所看到的图形系统是不一样的。例如在windows下运行,则显示的窗口是windows风格的窗口;而在UNIX下运行时,则显示的是UNIX风格的窗口。
  • 18. Component组件在AWT的概念中,窗口系统所显示的各种对象统称为构件:Button,Menu,List等等都是构件。 Component是代表构件最基本的类。 Component类中定义了各种窗口对象中最基本、最重要的方法和性质。随时随处都有可能利用Component定义的方法
  • 19. 类java.awt.Component是许多组件类的父类,Component类中封装了组件通用的方法和属性,如图形的组件对象、大小、显示位置、前景色和背景色、边界、可见性等,因此许多组件类也就继承了Component类的成员方法和成员变量,相应的成员方法包括:    getComponentAt(int x, int y)    getFont()    getForeground()    getName()    getSize()    paint(Graphics g)    repaint()    update()    setVisible(boolean b)    setSize(Dimension d)    setName(String name)等   
  • 20. 组件库1.按钮Button 2.标签Label 3. 单行文本输入区TextField 4. 文本输入区(TextArea) 5.复选框 Checkbox 6.复选框组CheckboxGroup 7. 下拉式菜单Choice 8. 列表List 9. Canvas 后面再讲。
  • 21. 11.2布局管理器 11.2.1 FlowLayout 11.2.2 BorderLayout 11.2.3 GridLayout 11.2.4 CardLayout 11.2.5 GridBagLayout 11.2.6 无布局管理器 11.2.7 容器的嵌套
  • 22. LayoutManager 布局管理器(LayoutManager):每个容器都有一个布局管理器,当容器需要对某个组件进行定位或判断其大小尺寸时,就会调用其对应的布局管理器。   为了使我们生成的图形用户界面具有良好的平台无关性,Java语言中,提供了布局管理器这个工具来管理组件在容器中的布局,而不使用直接设置组件位置和大小的方式。   在程序中安排组件的位置和大小时,应该注意以下两点:   1.容器中的布局管理器负责各个组件的大小和位置,因此用户无法在这种情况下设置组件的这些属性。如果试图使用Java 语言提供的setLocation(),setSize(),setBounds() 等方法,则都会被布局管理器覆盖。   2.如果用户确实需要亲自设置组件大小或位置,则应取消该容器的布局管理器,方法为:    setLayout(null);
  • 23. 11.2.1 FlowLayout FlowLayout 是Panel,Applet的缺省布局管理器。其组件的放置规律是从上到下、从左到右进行放置,如果容器足够宽,第一个组件先添加到容器中第一行的最左边,后续的组件依次添加到上一个组件的右边,如果当前行已放置不下该组件,则放置到下一行的最左边。 当容器的大小发生变化时,用FlowLayout管理的组件会发生变化,其变化规律是:组件的大小不变,但是相对位置会发生变化。例如上图中有三个按钮都处于同一行,但是如果把该窗口变窄,窄到刚好能够放下两个按钮,则第三个按钮将放到第二行。
  • 24. 11.2.1 FlowLayout
  • 25. // TestFlowLayout.java import java.awt.*; import java.awt.event.*; public class TestFlowLayout extends WindowAdapter { public TestFlowLayout() { } public void windowClosing( WindowEvent e){ System.exit(0); } public static void main(String arg[]) { Frame frame = new Frame("Test Flow Layout"); frame.setSize(300,150); frame.addWindowListener(new TestFlowLayout());//为“关闭”按钮添加窗口响应事件。
  • 26. Button button1 = new Button("First Button"); Button button2 = new Button("Second Button"); Button button3 = new Button("Third Button"); Button button4 = new Button("Fourth Button"); frame.setLayout(new FlowLayout(FlowLayout.LEFT)); // 缺省的对齐方式居中对齐。 frame.add(button1); frame.add(button2); frame.add(button3); frame.add(button4); frame.setVisible(true); } }
  • 27. 11.2.2 BorderLayout BorderLayout 是Window,Frame和Dialog的缺省布局管理器。BorderLayout布局管理器把容器分成5个区域:North,South,East,West和Center,每个区域只能放置一个组件。如果使用了BorderLayout布局,当容器的大小发生变化,其变化规律为:组件的相对位置不变,大小发生变化。例如容器变高了,则North、South区域不变,West、Center、East区域变高;如果容器变宽了,West、East区域不变,North、Center、South区域变宽。不一定所有的区域都有组件,如果四周的区域(West、East、North、South区域)没有组件,则由Center区域去补充。
  • 28. 11.2.2 BorderLayout
  • 29. // TestBorderLayout.java import java.awt.*; import java.awt.event.*; public class TestBorderLayout extends WindowAdapter{ public TestBorderLayout() { } public void windowClosing(WindowEvent e){ System.exit(0); } public static void main(String[] args) { Frame frame = new Frame("Test Border Layout"); frame.setSize(300,200); frame.addWindowListener(new TestBorderLayout());
  • 30. Button button1 = new Button("东"); Button button2 = new Button("南"); Button button3 = new Button("西"); Button button4 = new Button("北"); Button button5 = new Button("中"); frame.setLayout(new BorderLayout(10,10)); frame.add("East",button1); frame.add("South",button2); frame.add("West",button3); frame.add("North",button4); frame.add("Center",button5); frame.setVisible(true); } }
  • 31. 11.2.3 GridLayout 将整个容器划分成n行,m列的网格,平均占据容器的空间。分配空间时,优先考虑行划分,兼顾列。当行列不能满足指定的数值时,则按行扩展列。例如:五个按钮,指定分两行两列显示,实际的结果如下图所示,自动扩展为3列。
  • 32. // TestGridLayout.java import java.awt.*; import java.awt.event.*; public class TestGridLayout extends WindowAdapter{ public TestGridLayout() { } public void windowClosing(WindowEvent e){ System.exit(0); } public static void main(String[] args) { Frame frame = new Frame("Test Grid Layout"); frame.setSize(300,200); frame.addWindowListener(new TestGridLayout());
  • 33. Button button1 = new Button("1"); Button button2 = new Button("2"); Button button3 = new Button("3"); Button button4 = new Button("4"); Button button5 = new Button("5"); frame.setLayout(new GridLayout(2,2,10,20)); frame.add(button1); frame.add(button2); frame.add(button3); frame.add(button4); frame.add(button5); frame.setVisible(true); } }
  • 34. 11.2.4 CardLayout CardLayout布局管理器能够帮助用户处理两个以至更多的成员共享同一显示空间,它把容器分成许多层,每层的显示空间占据整个容器的大小,但是每层只允许放置一个组件,当然每层都可以利用Panel来实现复杂的用户界面。牌布局管理器(CardLayout)就象一副叠得整整齐齐的扑克牌一样,有54张牌,但是你只能看见最上面的一张牌,每一张牌就相当于牌布局管理器中的每一层
  • 35. // TestCardLayout.java import java.awt.*; import java.awt.event.*; public class TestCardLayout extends WindowAdapter implements ActionListener{ private Frame frame; private CardLayout cardLayout; public void run() { frame = new Frame("Test Card Layout"); frame.setSize(150,120); frame.addWindowListener(this); Button button1 = new Button("卡片 1"); Button button2 = new Button("卡片 2"); Button button3 = new Button("卡片 3");
  • 36. Panel panel1 = new Panel(); Panel panel2 = new Panel(); Panel panel3 = new Panel(); panel1.add(button1); button1.addActionListener(this); panel2.add(button2); button2.addActionListener(this); panel3.add(button3); button3.addActionListener(this); cardLayout = new CardLayout(); frame.setLayout(cardLayout); frame.add(panel1,"第一张"); frame.add(panel2,"第二张"); frame.add(panel3,"第三张"); frame.setVisible(true); }
  • 37. public void windowClosing( WindowEvent e){ System.exit(0); } public void actionPerformed(ActionEvent e){ cardLayout.next(frame); } public static void main(String[] args) { TestCardLayout myCardLayout = new TestCardLayout(); myCardLayout.run(); } }
  • 38. 11.2.5 GridBagLayout GridBagLayout生成的布局管理器也是和GridLayout一样是使用网格来进行布局管理的,所不同之处在于GridBagLayout可以通过类GridBagConstraints 来控制容器内各个组件的大小,每 个 组 件 都 使用 一 个 GridBagConstraints  对 象 来 给 出 它 的 大小和摆放位置,这样就可以按照设计者的意图,改变组件的大小,把他们摆在设计者希望摆放的位置上.这种灵活性是前面几个布局管理器所不具备的。但也正是这种灵活性使得它成为java中最有弹性也是最复杂的一种布局管理器。
  • 39. 11.2.5 GridBagLayout
  • 40. 11.3AWT事件处理 11.3.1事件处理模型 11.3.2 AWT事件 11.3.3事件监听器 11.3.4事件适配器 11.3.5内部类和匿名类
  • 41. 11.3.1事件处理模型JDK1.0 和JDK1.1采用不同的事件处理模型,其中JDK1.0采用的是层次(hierarchal)模型,而JDK1.1采用的是委托(delegation)模型。了解两种模型的基本原理和差异将有助于我们更好的理解和掌握JDK1.1的事件模型
  • 42. 11.3.1事件处理模型1.  JDK1.0的层次事件模型 在层次事件模型中,当一个事件对象产生后,首先传递给直接相关的组件,该组件可以对事件进行处理,也可以忽略事件不处理。如果组件没有对事件进行处理,则AWT事件处理系统会将事件继续向上传递给组件所在的容器。同样,容器可以对事件处理,也可以忽略不处理。如果事件又被忽略,则AWT事件处理系统会将事件继续上传,以次类推,直到事件被处理,或是已传到顶层容器。
  • 43. 例如,在下图中,Button对象(包含在一个Frame上的Panel中)上的鼠标点击首先向Button发送一个动作事件。如果它没有被Button处理,这个事件会被送往Panel,如果它在那儿仍然没有被处理,这个事件会被送往Frame。
  • 44. 这种模型有一个显著的优点:它简单,而且非常适合面向对象的编程环境;说到底,所有的组件都继承了java.awt.Component类,而handleEvent()就在java.awt.Component类中。 然而,这种模型也存在缺点: (1)事件只能由产生这个事件的组件或包含这个组件的容器处理。这个限制违反了面向对象编程的一个基本原则:功能应该包含在最合适的类中。而最适合处理事件的类往往并不是源组件的容器层次中的成员。 (2)大量的CPU周期浪费在处理不相关的事件上。任何对于程序来说不相关或者并不重要的事件会沿容器层次一路传播,直到最后被抛弃。不存在一种简单的方法来过滤事件。 (3)为了处理事件,你必须定义接收这个事件的组件的子类,或者在基容器创建一个庞大的handleEvent()方法。
  • 45. 例子import java.awt.*; import java.awt.event.*; public class SubclassContainer{ public static void main(String args[]){ Frame windo; MyButton myButton; windo =new Frame("Sub Button Test"); myButton=new MyButton("sub button"); windo.setLayout(new FlowLayout()); windo.add(myButton); windo.resize(200,100); windo.show(); } }
  • 46. class windo extends Frame{ windo(String Labe){ super(Labe);} public boolean action(Event e,Object arg){ if(e.target instanceof Button){ System.out.println("Pressed Button:"+arg); } return true; } }
  • 47. 11.3.1事件处理模型1.  JDK1.1的授权事件模型 为了客服JDK1.0层次事件模型的缺点,JDK1.1引入了授权事件模型,在这个模型中, 事件处理是从一个事件源授权到一个或多个事件监听者,组件作为事件源可以触发事件,通过addXXXlistener方法向组件注册监听器,一个组件可以注册多个监听器,如果组件触发了相应类型的事件,此事件被传送给已注册的监听器,事件监听器负责处理事件的过程。
  • 48. 事件是只向注册的监听者报告的对象。每个事件都有一个对应的监听者接口,规定哪些方法必须在适合接收那种类型的事件的类中定义。实现了定义那些方法的接口的类可以注册为一个监听者。
  • 49. 案例 import java.awt.*; public class TestButton { public static void main(String args[]) { Frame f = new Frame("Test"); Button b = new Button("Press Me!"); b.addActionListener(new ButtonHandler()); f.add(b,"Center"); f.pack(); f.setVisible(true); } }
  • 50. ButtonHandler类是一个处理器类,事件将被委托给这个类。 import java.awt.event.*; public class ButtonHandler implements ActionListener { public void actionPerformed(ActionEvent e) { System.out.println("Action occurred"); System.out.println("Button's label is : “ + e.getActionCommand()); } }
  • 51. 11.3.1事件处理模型下面我们以按钮组件的单击事件为例,说明如何编写事件处理程序。 当用户单击按钮时,系统捕获这些操作并产生ActionEvent事件,然后将执行约定的ActionListener接口中的actionPerformed方法,而该方法的具体实现则委托给该方法所在的类。为此程序中必须: (1) 为按钮注册事件监听程序 public void addActionListener (ActionListener handler) 使用按钮的addActionListener()方法,注册一个ActionEvent事件监听程序。Handler为按钮委托的事件监听程序类对象。如果是本类,则用this指明,如 b.addActionListener(new ButtonHandler());
  • 52. 11.3.1事件处理模型(2) 实现ActionListener接口中actionPerformed方法 定义事件监听程序类handler,该类实现了ActionListener 接口,重写该接口中唯一的actionPerformed方法: public void actionPerformed( ActionEvent e) 当单击按钮时,系统产生ActionEvent事件,执行程序员为该方法编写的事件处理代码,并传递给该方法一个ActionEvent事件对象e。
  • 53. 11.3.2 AWT事件 在授权事件模型中,事件既是基础,又是联系各个部分的桥梁。首先,组件作为事件源产生事件,不同类型的组件会产生不同类型的事件。事件发生后,事件被传递给对应事件监听器中实现的事件处理方法,并且在事件中,包含着用户传递给系统的交互信息,如文本框中的输入内容等。 不同类型的事件由不同的Java类来表示,基类是java.util.EventObject, 所有的事件都是从它继承而来的。AWT为GUI事件定义了自己的基类,java.awt.AWTEvent,它是EventObject的子类。AWT事件的详细结构图见下图。
  • 54. 11.3.2 AWT事件
  • 55. AWT事件及监听器对应表
  • 56. (本页无文本内容)
  • 57. (本页无文本内容)
  • 58. 案例本例将跟踪鼠标被按下时,鼠标的移动情况(鼠标拖动)。这个范例还将监测当鼠标没有按下时,鼠标的移动情况(鼠标移动)。 当鼠标按下或没有按下时,移动鼠标产生的事件会被实现了MouseMotionListener接口的类的对象检取。这个接口要求定义两个方法,mouseDragged()和mouseMoved()。即使你只对鼠标拖动感兴趣,也必须提供这两个方法。然而,mouseMoved()的体可以是空的。 要检取其他鼠标事件,包括鼠标点击,必须定义MouseListener接口。这个接口包括若干个事件,即:mouseEntered, mouseExited, mousePressed, mouseReleased和 mouseClicked。 发生鼠标或键盘事件时,有关鼠标的位置和所按下的键的信息可以从事件中得到。
  • 59. (本页无文本内容)
  • 60. 代码:import java.awt.*; import java.awt.event.*; public class TwoListen implements MouseMotionListener, MouseListener { private Frame f; private TextField tf; public static void main(String args[]) { TwoListen two = new TwoListen(); two.go(); }
  • 61. public void go() { f = new Frame("Two listeners example"); f.add (new Label ("Click and drag the mouse"), "BorderLayout.NORTH"); tf = new TextField (30); f.add (tf, "BorderLayout.SOUTH"); f.addMouseMotionListener(this); f.addMouseListener (this); f.setSize(300, 200); f.setVisible(true); }
  • 62. // These are MouseMotionListener events public void mouseDragged (MouseEvent e) { String s = "Mouse dragging: X = " + e.getX() + " Y = " + e.getY(); tf.setText (s); } public void mouseMoved (MouseEvent e) { }
  • 63. // These are MouseListener events public void mouseClicked (MouseEvent e) { } public void mouseEntered (MouseEvent e) { String s = "The mouse entered"; tf.setText (s); } public void mouseExited (MouseEvent e) { String s = "The mouse has left the building"; tf.setText (s); } public void mousePressed (MouseEvent e) { } public void mouseReleased (MouseEvent e) { } }
  • 64. 11.3.3事件监听器 接收事件并对事件做出相应反映的对象称为事件监听器。Java.awt.event包中按照不同的事件类型定义了11个监听器接口,每类事件都有对应的事件监听器,监听器是接口,接口中定义了事件发生时可调用的方法,一个类可以实现监听器的一个或多个接口,这就需要把所实现接口中所定义的所有方法实现,当对其中的方法不感兴趣时,也可以将方法体用一对();而不给出具体方法。
  • 65. java.awt.event包中定义的事件适配器类包括以下几个:   1)ComponentAdapter( 组件适配器)   2)ContainerAdapter( 容器适配器)   3)FocusAdapter( 焦点适配器)   4)KeyAdapter( 键盘适配器)   5)MouseAdapter( 鼠标适配器)   6)MouseMotionAdapter( 鼠标运动适配器)   7)WindowAdapter( 窗口适配器)
  • 66. 对于适配器类的定义,我们以WindowAdapter类为例进行说明 先定义接口 public interface WindowListener extends EventListener { public void windowOpened(WindowEvent e); public void windowClosing(WindowEvent e); public void windowClosed(WindowEvent e); public void windowIconified(WindowEvent e); public void windowDeiconified(WindowEvent e); public void windowActivated(WindowEvent e); public void windowDecativated(WindowEvent e); }
  • 67. public abstract class WindowAdapter implement WindowListener{ public void windowOpened(WindowEvent e) {} public void windowIconified(WindowEvent e) {} public void windowDeiconified(WindowEvent e) {} public void windowClosed(WindowEvent e) {} public void windowActivated(WindowEvent e) { } public void windowDeactivated(WindowEvent e) {} }
  • 68. 11.3.4事件适配器案例: import java.awt.*; import java.awt.event.*; class WindowClosing extends WindowAdapter { public void windowClosing(WindowEvent e){ System.exit(0); } }
  • 69. 11.3.5内部类和匿名类 为了简化事件源和监听器之间的关系,java的事件处理中引入和使用了内部类(Inner Class)和匿名类(Anonymous Class),内部类是被定义于另一个类中的类,即类的嵌套。由于内部类可以访问外部类的成员方法和变量,包括私有的成员。所有实现监听器时,采用内部类,匿名类变成非常容易实现其功能。 下面我们通过例子来体会通过主类和内部类两种方法实现监听器的不同之处。
  • 70. 11.3.5内部类和匿名类比较两种实现方法,首先,用主类做接收器,由于实现了多个监听器接口,所以各个接口中的方法,全部要在主类中实现,多种方法堆砌在一起,加大了程序阅读和维护的难度。相反,用内部类和匿名类做接收器,每个接收器就是一个独立的类,不仅阅读方便,并且由于减少了同主类的耦合性,从而使代码的重用性大大提高了。其次,观察第二种实现方法里的actionPerformed方法,由于有多个组件都可能发生actionEvent事件,所有在处理前首先要判断传递过来事件的事件源是哪一个组件,显然在程序的执行效率上,同第一种方法也是有差距的。通过比较,我们认为在多个方面第一种方法都要优于第二种,所以用内部类和匿名类来进行事件处理是我们推荐的好的实现事件处理的方法。
  • 71. (本页无文本内容)
  • 72. 案例//InnerClass.java import java.awt.*; import java.awt.event.*; public class InnerClass extends Frame{ Button b1=new Button("Button 1"); Button b2=new Button("Button 2"); public InnerClass() { setLayout(new FlowLayout()); b1.addActionListener(new b1L()); b2.addActionListener(new b2L()); add(b1); add(b2); setSize(200,200); setVisible(true); addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){System.exit(1);}; });//用匿名类实现窗口关闭 。。。。。。。。。。
  • 73. 11.4 常用AWT组件使用举例 11.4.1基本组件 11.4.2菜单
  • 74. 11.4.1基本组件 1.按钮Button 2.标签Label 3. 单行文本输入区TextField 4. 文本输入区(TextArea) 5.复选框 Checkbox 6. 复选框组CheckboxGroup 7. 下拉式菜单Choice 8. 列表List 9. Canvas
  • 75. 11.4.2菜单 无法直接将菜单添加到容器的某一位置,也无法使用布局管理器对其加以控制。菜单只能被添加到菜单容器(MenuBar)中。 设计菜单时,首先创建MenuBar实例,用add()方法添加到Frame容器中,然后,创建Menu,并用add()方法依次加入到MenuBar上,最后,创建MenuItem,用add()方法把MenuItem加入到Menu上。
  • 76. 11.4.2菜单        MenuBar 只能被添加到Frame对象中,作为整个菜单树的根基。   Frame fr = new Frame("MenuBar");   MenuBar mb = new MenuBar();   fr.setMenuBar(mb);   fr.setSize(150,100);   fr.setVisible(true);
  • 77. 11.4.2菜单         Menu   下拉菜单。它可以被添加到MenuBar中或其它Menu中。 Frame fr = new Frame("MenuBar");   MenuBar mb = new MenuBar();   fr.setMenuBar(mb);   Menu m1 = new Menu("File");   mb.add(m1); 将Menu 添加到其它Menu中可以实现多级子菜单的功能。
  • 78. 11.4.2菜单   MenuItem MenuItem是菜单树中的"叶子节点"。MenuItem通常被添加到一个Menu中。对于MenuItem对象可以注册事件监听器,使其能够完成相应的操作。   Menu m1 = new Menu("File");   MenuItem mi1 = new MenuItem("Save");
  • 79. 11.5 Swing组件设计用户界面 11.5.1 Swing组件 11.5.2使用Swing的基本规则
  • 80. 11.5.1 Swing组件Swing是Java2平台的核心部分,包含大量的组件,从简单的标签(Jlable)、按钮(Jbutton)到复杂的表格(Jtable)、树(Jtree)。几乎所有Swing组件都是从Jcomponent派生来得,而Jcomponent是从AWT的Container类继承而来的。所以, Swing更像是AWT的扩展,而非AWT的替代。观察AWT组件和Swing组件,发现几乎每个AWT组件都有一个对应的以J开头的Swing组件,例如,Jbutton对应Button,JPanel对应Panel。不过有很多的Swing组件没有对应的AWT组件,这是因为AWT的设计初衷是支持开发小应用程序的的简单用户界面,不能实现一些打印、导航等负责功能,而Swing的出现,弥补了这一缺陷。
  • 81. 11.5.1 Swing组件同AWT组件相比,Swing组件有很多的优点,清楚的了解这些优点,将有助于我们更好的使用Swing组件。下面我们将详细讨论这些优点: 工具提示条(tooltip) 图标(icon) 边框 (border) 可插拔的界面外观(pluggable) 可存取性(accessibility) 双缓冲(double-buffering)
  • 82. 11.5.2使用Swing的基本规则 Swing的程序设计一般可按照下列流程进行: 1)         引入Swing包 2)         选择"外观和感觉" 3)         设置顶层容器 4)         设置按钮和标签 5)         向容器中添加组件 6)         在组件周围添加边界 7)         进行事件处理
  • 83. 11.6 AWT图形和Java2D图形 11.6.1AWT图形 11.6.2 Java2D图形
  • 84. 11.6.1AWT图形图形上下文和图形对象 坐标 颜色 字体
  • 85. 11.6.1AWT图形画线、矩形和椭圆 下面的程序说明了如何绘制各种线条、矩形、立体矩形、圆角矩形和椭圆。 import java.awt.*; import java.awt.event.*; import javax.swing.*;  public class Draw extends JFrame{ private String s="Using drawString!";   public Draw() { super("Drawing lines,rectangles and ovals"); setSize(400,165); show(); }
  • 86. 11.6.1AWT图形public void paint(Graphics g){ g.setColor(Color.red); g.drawLine(5,30,350,30);   g.setColor(Color.blue); g.drawRect(5,40,90,55); g.fillRect(100,40,90,55); g.setColor(Color.cyan); g.drawRoundRect(290,40,90,55,20,20); g.fillRoundRect(195,40,90,55,20,20);   g.setColor(Color.yellow); g.draw3DRect(5,100,90,55,true); g.fill3DRect(100,100,90,55,false);
  • 87. 11.6.1AWT图形g.setColor(Color.magenta); g.drawOval(195,100,90,55); g.fillOval(290,100,90,55); } public static void main(String[] args) { Draw d=new Draw(); d.addWindowListener( new WindowAdapter(){ public void windowClosing (WindowEvent e){ System.exit(0); } }); }
  • 88. 11.6.1AWT图形程序运行界面如图:
  • 89. 11.6.2 Java2D图形 Java 2D API是JFC (Java Fundation Classes)的一员,加强了传统AWT( Abstract Windowing Toolkit )的描绘功能。在 JDK1.2中已经支持 Java 2D 的使用。透过Java 2D API , 可以轻松地描绘出任意的几何图形、运用不同的填色效果、对图形做旋转( rotate)、缩放( scale)、扭曲( shear)等。当然,Java2D API还有许多增强AWT能力的部分,像是处理影像档案可以有不同的滤镜(filter)效果、对于任意的几何图形能做碰撞侦测(hit detection)、图形重叠混色计算(composite)等功能。不过,这些功能相对于本书来说显得太广泛了,所以在书中就不详细介绍了。
  • 90. 11.6.2 Java2D图形Java2D最基本的抽象之一就是java.awt.Shape,很明显,这个接口描述的是形状,这里说的形状不仅包括矩形、圆形等封闭曲线,还包括直线、抛物线等不封闭的曲线。Java2Dgraphics2D类行医了几种关于Shape对象的非常基础的操作:draw()绘制Shape;fill()填充Shape;clip()限制当前的绘图区域为指定的Shape;hit()检测给定的矩形是否落在给定的形状内或智商。此外,AffineTransform类的方法允许Shape对象进行任意伸缩、旋转、平移和剪切。 下面我们用程序来演示应用Java2D API画图的具体步骤:
  • 91. 11.6.2 Java2D图形import javax.swing.*; import java.awt.event.*; import java.awt.*; import java.awt.geom.*; //import java.awt.image.*;   public class Shapes extends JFrame{ public Shapes() { super("Drawing 2D shapes"); setSize(265,160); show(); }
  • 92. 11.6.2 Java2D图形public void paint(Graphics g){ Graphics2D g2d=(Graphics2D)g; g2d.setPaint(new GradientPaint(5,30,Color.blue,35,100,Color.yellow,true)); g2d.fill(new Ellipse2D.Double(5,30,65,100)); g2d.setPaint(Color.red); g2d.setStroke(new BasicStroke(10.0f)); g2d.draw(new Rectangle2D.Double(80,30,65,100));   g2d.setPaint(Color.white); g2d.setStroke(new BasicStroke(6.0f)); g2d.draw(new Arc2D.Double(160,30,75,100,0,270,Arc2D.PIE)); }
  • 93. 11.6.2 Java2D图形public static void main(String[] args) { Shapes s=new Shapes(); s.addWindowListener( new WindowAdapter(){ public void windowClosing (WindowEvent e){ System.exit(0); } });   } }
  • 94. 11.6.2 Java2D图形程序运行界面如图: