• 1. 图形编程及事件处理
  • 2. 提问请讲出三种布局管理器,并解释其意义 讲一下JFrame继承体系中,每个类的意义 JFrame和JPanel的默认布局管理器
  • 3. 学习目标能够用Java创建图形界面 掌握几种常用的布局管理器 掌握Java事件处理机制 学会使用事件适配器 掌握匿名内部类在事件处理中的使用
  • 4. 本课内容AWT与Swing 组件和容器 布局管理器 AWT事件处理机制
  • 5. 1. 抽象窗口工具集(AWT)AWT– Abstract Window Toolkit GUI -- Graphical User Interface AWT中定义了多种类和接口,用于在Java Application/Applet中进行GUI设计 Java程序要显示的GUI组件必须是抽象类Component或MenuComponent的子类
  • 6. SwingSwing
  • 7. java.awt 包java.awt包 提供了基本的java程序GUI设计工具。 Component/MenuComponent Container LayoutManager
  • 8. 2. 组件(Component)Java的图形用户界面的最基本组成部分是组件,组件是一个可以以图形化的方式显示在屏幕上并能与用户进行交互的对象,例如一个按钮,一个标签等。 组件不能独立地显示出来,必须将组件放在一定的容器中才可以显示出来。
  • 9. 容 器(Container)容器(Container)实际上是Component的子类,因此容器类对象本身也是一个组件,具有组件的所有性质,另外还具有容纳其它组件和容器的功能。 容器类对象可使用方法add()添加组件 两种主要的容器类型 Window: 可自由停泊的顶级窗口 JPanel:可作为容器容纳其它组件,但不能独立存在,必须被添加到其它容器中(如Window 或 Applet)
  • 10. 组件定位Java组件在容器中的位置和尺寸由布局管理器决定 如要人工控制组件在容器中的大小位置,可取消布局管理器,然后使用Component类的下述成员方法: setLocation() setSize() 设置大小 setBounds() 设置位置
  • 11. JFrame类JFrame类是抽象类Window的子类 JFrame对象显示效果是一个“窗口”,带有标题和尺寸重置角标 默认初始化为不可见的,可使用setVisible(true)方法使之变为可见 默认的布局管理器是BorderLayout 可使用setLayout()方法改变其默认布局管理器
  • 12. JFrame类继承层次java.lang.Object | +----java.awt.Component | +----java.awt.Container | +----java.awt.Window | +----java.awt.JFrame
  • 13. 案例1001 import java.awt.*; public class TestJFrame { public static void main( String args[]) { JFrame f = new JFrame("My First Test"); f.setSize( 170,100); f.setVisible( true); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } }
  • 14. 将窗口显示在屏幕中央
  • 15. JPanel类java.lang.Object | +----java.awt.Component | +----java.awt.Container | +----java.awt.JPanel 提供容纳组件的空间 可以采用和所在容器不同的布局管理器 JPanel类的继承层次
  • 16. 案例1002
  • 17. 3. 布局管理器为了使我们生成的图形用户界面具有良好的平台无关性,Java语言中,提供了布局管理器这个工具来管理组件在容器中的布局,而不使用直接设置组件位置和大小的方式。 每个容器都有一个布局管理器,当容器需要对某个组件进行定位或判断其大小尺寸时,就会调用其对应的布局管理器。
  • 18. 容器布局 (Container Layouts) FlowLayout BorderLayout GridLayout CardLayout GridBagLayout
  • 19. 默认布局管理器ComponentContainerWindowJPanelJFrameDialogAppletBorderLayoutFlowLayout
  • 20. 3.1 FlowLayout布局管理器FlowLayout是JPanel类的默认布局管理器 FlowLayout布局对组件逐行定位,行内从左到右,一行排满后换行 默认对齐方式为居中对齐 不改变组件的大小,按组件原有尺寸显示组件.可在构造方法中设置不同的组件间距、行距及对齐方式
  • 21. 案例1003import java.awt.*; public class TestFlowLayout { public static void main(String args[]) { JFrame f = new JFrame("Flow Layout"); JButton JButton1 = new JButton("Ok"); JButton JButton2 = new JButton("Open"); JButton JButton3 = new JButton("Close"); f.setLayout(new FlowLayout()); f.add(JButton1); f.add(JButton2); f.add(JButton3); f.setSize(100,100); f.setVisible(true); } }
  • 22. FlowLayout 的构造方法new FlowLayout(FlowLayout.RIGHT,20,40); 右对齐,组件之间水平间距20个像素,竖直间距40个像素; new FlowLayout(FlowLayout.LEFT); 左对齐,水平和竖直间距为缺省值:5; new FlowLayout(); 使用缺省的居中对齐方式,水平和竖直间距为缺省值:5;
  • 23. 3.2 BorderLayout 布局管理器BorderLayout是JFrame类的默认布局管理器 BorderLayout将整个容器的布局划分成东、西、南、北、中五个区域,组件只能被添加到指定的区域 如不指定组件的加入部位,则默认加入到Center区域 每个区域只能加入一个组件,如加入多个,则先前加入的组件会被遗弃
  • 24. BorderLayout 布局管理器BorderLayout型布局容器尺寸缩放原则 北、南两个区域只能在水平方向缩放(宽度可调整) 东、西两个区域只能在垂直方向缩放(高度可调整) 中部可在两个方向上缩放North South West Eest Center
  • 25. 案例1004import java.awt.*; public class TestBorderLayout { public static void main(String args[]) { JFrame f = new JFrame("Border Layout"); JButton bn = new JButton("BN"); JButton bs = new JButton("BS"); JButton bw = new JButton("BW"); JButton be = new JButton("BE"); JButton bc = new JButton("BC"); f.add(bn, "North"); f.add(bs, "South"); f.add(bw, "West"); f.add(be, "East"); f.add(bc, "Center"); f.setSize(200,200); f.setVisible(true); } }
  • 26. 3.3 GridLayout 布局管理器GridLayout型布局管理器将布局划分成规则的矩形网格,每个单元格区域大小相等. 组件被添加到每个单元格中,先从左到右添满一行后换行,再从上到下. 在GridLayout构造方法中指定分割的行数和列数. new GridLayout(3,4);
  • 27. 案例1005import java.awt.*; public class TestGridLayout { public static void main(String args[]) { JFrame f = new JFrame("GridLayout Example"); JButton b1 = new JButton("b1"); JButton b2 = new JButton("b2"); JButton b3 = new JButton("b3"); JButton b4 = new JButton("b4"); JButton b5 = new JButton("b5"); JButton b6 = new JButton("b6"); f.setLayout (new GridLayout(3,2)); f.add(b1); f.add(b2); f.add(b3); f.add(b4); f.add(b5); f.add(b6); f.pack(); f.setVisible(true); } }
  • 28. 3.4 CardLayout 布局管理器CardLayout布局管理器能够帮助用户处理两个以至更多的成员共享同一显示空间,就好象一叠卡片摞在一起。 注意:在一张卡片中只能显示一个组件,因此可以使用容器嵌套方法显示多个组件。
  • 29. 案例1006综合应用import java.awt.*; public class NestedContainer { public static void main(String args[]) { JFrame f = new JFrame("NestedContainer"); JButton b0 = new JButton("display Area"); JPanel p = new JPanel(); p.setLayout(new GridLayout(2,2)); JButton b1 = new JButton("1"); JButton b2 = new JButton("2"); JButton b3 = new JButton("3"); JButton b4 = new JButton("4"); p.add(b1); p.add(b2); p.add(b3); p.add(b4); f.add(b0, "North"); f.add(p, "Center"); f.pack(); f.setVisible(true); } }
  • 30. 布局管理器总结(1)JFrame JFrame是一个顶级窗口。 JFrame的缺省布局管理器为BorderLayout。 JPanel JPanel无法单独显示,必须添加到某个容器中。 JPanel的缺省布局管理器为FlowLayout。 当把JPanel作为一个组件添加到某个容器中后,该JPanel仍然可以有自己的布局管理器。因此,可以利用JPanel使得BorderLayout中某个区域显示多个组件。
  • 31. 布局管理器总结(2) 在程序中安排组件的位置和大小时,应注意: 容器中的布局管理器负责各个组件的大小和位置,因此用户无法在这种情况下设置组件的这些属性。如果试图使用Java语言提供的setLocation(),setSize(),setBounds()等方法,则都会被布局管理器覆盖。 如果用户确实需要亲自设置组件大小或位置,则应取消该容器的布局管理器,方法为: setLayout(null);
  • 32. 4. AWT 绘图可以在任何Java组件上绘图(通常Canvas和JPanel组件更适合用于绘图) 每个Java组件都有一个public void paint(Graphics g)方法专门用于绘图目的,每次重画该组件时都自动调用paint方法。 每个Java组件都有一个Graphics类型的属性,该属性(对象)真正完成在相应组件上的绘图功能。 Graphics类中实现了许多绘图方法: -- 绘制边框(非填充图形) -- 填充特定区域 -- 绘制其它形状图形
  • 33. import java.awt.*; class SubJPanel extends JPanel{ public void paint(Graphics g){ g.drawString("this is a drawing test!",20,20); g.drawLine(30,60,100,120); g.draw3DRect(60,50,70,30,false); } } public class AWTDrawing2 { private JFrame f = new JFrame(" Hello Out There!"); private JPanel p = new SubJPanel(); public void launchJFrame() { f.add(p); f.setSize(170,170); f.setBackground( new Color(89,145,145)); f.setVisible( true); } public static void main( String args[]) { AWTDrawing2 guiWindow = new AWTDrawing2(); guiWindow.launchJFrame(); } }AWT 绘图举例
  • 34. 画背景图等
  • 35. 5. 什么是事件?事件(Event) –用户用于交互而产生的键盘或鼠标动作. 事件源(Event source) – 产生事件的组件 事件处理方法(Event handler) – 能够接收、解析和处理事件类对象、实现和用户交互的方法 用户鼠标点击actionPerformed(ActionEvent e){ …… }①②ActionEvent
  • 36. 事件处理模型(Delegation Model) 一个事件可以被发送到多个不同的处理方法.如果关注某个组件产生的事件 ,则可以在该组件上注册适当的事件处理方法,实现这种方法的对象称为事件监听器。 用户鼠标点击actionPerformed(ActionEvent e){ …… }//事件处理方法2①②ActionEventactionPerformed(ActionEvent e){ …… }//事件处理方法1②
  • 37. 案例1009import java.awt.*; import java.awt.event.*; public class TestActionEvent { public static void main(String args[]) { JFrame f = new JFrame("Test"); JButton b = new JButton("Press Me!"); Monitor bh = new Monitor(); b.addActionListener(bh); f.add(b,BorderLayout.CENTER); f.pack(); f.setVisible(true); } } class Monitor implements ActionListener { public void actionPerformed(ActionEvent e) { System.out.println("a JButton has been pressed"); } }
  • 38. 案例10
  • 39. 事件代理模型综述Java GUI设计中,通过注册监听器的方式对所关注的事件源进行监控。 注册监听器时应指明该监听器监控(感兴趣)的事件种类。 当事件源发生了某种类型的事件时,只触发事先已就该种事件类型注册过的监听器。
  • 40. AWT事件层次结构图
  • 41. ActionEvent:对应按钮点击、菜单选择、列表框选择、在文本域中按回车键等。 AdjustmentEvent:用户调整滚动条。 ItemEvent:用户从一组选择框或者列表项中进行选择。 TextEvent:文本域或者文本框中的内容发生改变。 ComponentEvent:组件大小改变、移动、显示或隐藏 KeyEvent:键盘上的一个键被按下或者释放。 MouseEvent:鼠标按键被按下、释放、鼠标移动或拖动 FocusEvent:组件获得焦点或者失去焦点。 WindowEvent:窗口被激活、屏蔽、最小化、最大化或关闭 ContainerEvent:添加或者删除一个组件。
  • 42. 5.2 GUI事件及监听器接口事件类型相应监听器接口监听器接口中的方法ActionActionListeneractionPerformed(ActionEvent)ItemItemListeneritemStateChanged(ItemEvent)MouseMouseListenermousePressed(MouseEvent) mouseReleased(MouseEvent) mouseEntered(MouseEvent) mouseExited(MouseEvent) mouseClicked(MouseEvent)Mouse Motion MouseMotionListenermouseDragged(MouseEvent) mouseMoved(MouseEvent)KeyKeyListenerkeyPressed(KeyEvent) keyReleased(KeyEvent) keyTyped(KeyEvent)FocusFocusListenerfocusGained(FocusEvent) focusLost(FocusEvent)
  • 43. 事件类型相应监听器接口监听器接口中的方法ComponentComponentListenercomponentMoved(ComponentEvent) componentHidden (ComponentEvent) componentResized(ComponentEvent) componentShown(ComponentEvent)WindowWindowListenerwindowClosing(WindowEvent) windowOpened(WindowEvent) windowIconified(WindowEvent) windowDeiconified(WindowEvent) windowClosed(WindowEvent) windowActivated(WindowEvent) windowDeactivated(WindowEvent)ContainerContainerListenercomponentAdded(ContainerEvent) componentRemoved(ContainerEvent)TextTextListenertextValueChanged(TextEvent)
  • 44. (本页无文本内容)
  • 45. 5.3 多重监听器一般情况下,事件源可以产生多种不同类型的事件,因而可以注册(触发)多种不同类型的监听器。 一个事件源组件上可以注册多个监听器,针对同一个事件源的同一种事件也可以注册多个监听器,一个监听器可以被注册到多个不同的事件源上。
  • 46. import java.awt.*; import java.awt.event.*; public class TestMultiListener implements MouseMotionListener,MouseListener { JFrame f = new JFrame("多重监听器测试"); TextField tf = new TextField(30); public TestMultiListener(){ Label l = new Label("请按下鼠标左键并拖动"); l.setBackground(Color.red); f.add(l,"North"); f.add(tf, "South"); f.setBackground(new Color(120,175,175)); f.addMouseMotionListener(this); f.addMouseListener(this); f.setSize(300, 200); f.setVisible(true); } public static void main(String args[]) { TestMultiListener t = new TestMultiListener(); } //未完,接下页多重监听器举例
  • 47. public void mouseDragged(MouseEvent e) { String s = "鼠标拖动到位置(" + e.getX() + "," + e.getY() + ")"; tf.setText(s); } public void mouseEntered(MouseEvent e) { String s = "鼠标已进入窗体"; tf.setText(s); } public void mouseExited(MouseEvent e) { String s = "鼠标已移出窗体"; tf.setText(s); } // 未使用的MouseMotionListener和MouseListener接口中的方法,也必须实现 public void mouseMoved(MouseEvent e) { } public void mousePressed(MouseEvent e) { } public void mouseClicked(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } }
  • 48. 5.4 事件适配器(Event Adapter)为简化编程,针对大多数事件监听器接口定义了相应的实现类----事件适配器类,在适配器类中,实现了相应监听器接口中所有的方法,但不做任何事情。 在定义监听器类时就可以继承事件适配器类,并只重写所需要的方法。 ComponentAdapter(组件适配器) ContainerAdapter(容器适配器) FocusAdapter(焦点适配器) KeyAdapter(键盘适配器) MouseAdapter(鼠标适配器) MouseMotionAdapter(鼠标运动适配器) WindowAdapter(窗口适配器)
  • 49. 事件适配器用法举例定义一个监听器类,用于处理鼠标点击事件: 1 import java.awt.*; 2 import java.awt.event.*; 3 4 public class Monitor3 extends MouseAdapter { 5 6 // 当只需要处理mouseClick事件时,可以继承 7 // 事件适配器类MouseAdapter,以避免实现接口 8 // 时不得不重写接口中定义的所有方法 9 10 public void mouseClicked(MouseEvent e) { 11 // 处理代码…… 12 } 13 }
  • 50. 5.5 内部类在事件处理中的使用案例10-12 import java.awt.event.*; public class TestInner { JFrame f = new JFrame("内部类测试"); TextField tf = new TextField(30); public TestInner(){ f.add(new Label("请按下鼠标左键并拖动"), "North"); f.add(tf, "South"); f.setBackground(new Color(120,175,175)); InnerMonitor im = new InnerMonitor(); f.addMouseMotionListener(im); f.addMouseListener(im); f.setSize(300, 200); f.setVisible(true); } public static void main(String args[]) { TestInner t = new TestInner (); } //未完,接下页
  • 51. class InnerMonitor implements MouseMotionListener, MouseListener { public void mouseDragged(MouseEvent e) { String s = "鼠标位置(" + e.getX() + "," + e.getY() + ")"; tf.setText(s); } public void mouseEntered(MouseEvent e) { String s = "鼠标已进入窗体"; tf.setText(s); } public void mouseExited(MouseEvent e) { String s = "鼠标已移出窗体"; tf.setText(s); } public void mouseMoved(MouseEvent e) { } public void mousePressed(MouseEvent e) { } public void mouseClicked(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } }//end of inner class InnerMonitor }//end of class TestInner
  • 52. 普通内部类
  • 53. 静态内部类
  • 54. 案例1013import java.awt.*; import java.awt.event.*; public class TestAnonymous { JFrame f = new JFrame("匿名内部类测试"); TextField tf = new TextField(30); public TestAnonymous(){ f.add(new Label("请按下鼠标左键并拖动"), "North"); f.add(tf, "South"); f.addMouseMotionListener(new MouseMotionAdapter(){ public void mouseDragged(MouseEvent e) { String s = "鼠标拖动到位置(" + e.getX() + "," + e.getY() + ")"; tf.setText(s); } }); f.setSize(300, 200); f.setVisible(true); } public static void main(String args[]) { TestAnonymous t = new TestAnonymous(); } }
  • 55. 案例1014import java.awt.*; import java.awt.event.*; public class TestAnonymous2 { JFrame f = new JFrame("Test"); TextField tf = new TextField(10); JButton b1 = new JButton("Start"); public TestAnonymous2(){ f.add(b1,"North"); f.add(tf,"South"); b1.addActionListener(new ActionListener(){ private int i; public void actionPerformed(ActionEvent e) { tf.setText(e.getActionCommand() + ++i); } }); f.pack(); f.setVisible(true); } public static void main(String args[]) { new TestAnonymous2(); } }
  • 56. 小结容器和组件(JFrame、JPanel) 布局管理器(FlowLayout、BorderLayout、GridLayout)的使用 Java的事件处理机制
  • 57. 课后作业编写一个程序,达到图示结果,要求使用布局管理器。调节窗口的大小,观察各个组件位置的变化情况。 编写一个程序,达到以下功能:在鼠标按下的两点之间画一条直线,直线的一个端点为上次鼠标点击的坐标点,另一个端点为当前点击的坐标点。要求:能正确的关闭窗口。
  • 58. 课后作业3 窗口居中显示
  • 59. 作业第一题
  • 60. 鼠标点击画线