《面向对象程序设计(java)》第十三周学习总结
第一部分:理论知识学习部分
1、事件源(event source):能够产生事件的对象都可 以成为事件源,如文本框、按钮等。一个事件源是一个 能够注册监听器并向监听器发送事件对象的对象。
事件监听器(event listener):事件监听器对象接 收事件源发送的通告(事件对象),并对发生的事件作 出响应。一个监听器对象就是一个实现了专门监听器接 口的类实例,该类必须实现接口中的方法,这些方法当 事件发生时,被自动执行。
2、事件对象(event object):Java将事件的相关信息 封装在一个事件对象中,所有的事件对象都最终派生于 java.util.EventObject类。不同的事件源可以产生不 同类别的事件
AWT事件处理机制的概要:
3、监听器对象:是一个实现了特定监听器接口( listener interface)的类实例。
4、事件源:是一个能够注册监听器对象并发送事件对 象的对象。
5、当事件发生时,事件源将事件对象自动传递给所 有注册的监听器。
6、监听器对象利用事件对象中的信息决定如何对事 件做出响应。
GUI设计中,程序员需要对组件的某种事件进行响应和处理时,必须完成两个步骤:
1) 定义实现某事件监听器接口的事件监听器类,并具体化接口中声明的事件处理抽象方法。
2) 为组件注册实现了规定接口的事件监听器对象;
7、注册监听器方法 eventSourceObject.addEventListener(eventListenerObject)
8、下面是监听器的一个示例: ActionListener listener = …;
JButton button=new JButton(“Ok”); button.addActionListener(listener);
9、动作事件(ActionEvent):当特定组件动作(点 击按钮)发生时,该组件生成此动作事件。
10、该 事 件 被 传 递 给 组 件 注 册 的 每 一 个 ActionListener 对象, 并 调 用 监 听 器 对 象 的 actionPerformed方法以接收这类事件对象。
11、能够触发动作事件的动作,主要包括:
(1) 点击按钮
(2) 双击一个列表中的选项;
(3) 选择菜单项;
(4) 在文本框中输入回车。
第二部分:实验部分
1.实验名称:实验十三 图形界面事件处理技术
2. 实验目的:
(1) 掌握事件处理的基本原理,理解其用途;
(2) 掌握AWT事件模型的工作机制;
(3) 掌握事件处理的基本编程模型;
(4) 了解GUI界面组件观感设置方法;
(5) 掌握WindowAdapter类、AbstractAction类的用法;
(6) 掌握GUI程序中鼠标事件处理技术。
3.实验内容和步骤
实验1: 导入第11章示例程序,测试程序并进行代码注释。
测试程序1:
l 在elipse IDE中调试运行教材443页-444页程序11-1,结合程序运行结果理解程序;
运行结果如下:
l 在事件处理相关代码处添加注释;
1 import java.awt.*; 2 import java.awt.event.*; 3 import javax.swing.*; 4 5 /** 6 * A frame with a button panel 7 */ 8 public class ButtonFrame extends JFrame { 9 private JPanel buttonPanel; 10 private static final int DEFAULT_WIDTH = 300; 11 private static final int DEFAULT_HEIGHT = 200; 12 13 public ButtonFrame() { 14 setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); 15 16 // create buttons 17 JButton yellowButton = new JButton("Yellow"); 18 JButton blueButton = new JButton("Blue"); 19 JButton redButton = new JButton("Red"); 20 21 // 生成三个按钮对象 22 buttonPanel = new JPanel(); 23 24 // add buttons to panel 25 buttonPanel.add(yellowButton); 26 buttonPanel.add(blueButton); 27 buttonPanel.add(redButton); 28 // 用add方法添加三个按钮组件(只有容器组件有add方法) 29 // add panel to frame 30 add(buttonPanel); 31 32 // create button actions 33 34 ColorAction yellowAction = new ColorAction(Color.YELLOW); ColorAction 35 blueAction = new ColorAction(Color.BLUE); ColorAction redAction = new 36 ColorAction(Color.RED); 37 38 // 生成三个类对象ColorAction,颜色值为静态常量值 39 // associate actions with buttons 40 41 yellowButton.addActionListener(yellowAction); 42 blueButton.addActionListener(blueAction); 43 redButton.addActionListener(redAction); 44 } 45 46 /** 47 * An action listener that sets the panel's background color. 48 */ 49 private class ColorAction implements ActionListener 50 // 定义一个私有类,监听器类对象(ColorAction) 51 { 52 private Color backgroundColor; 53 54 public ColorAction(Color c) { 55 backgroundColor = c; 56 } 57 58 public void actionPerformed(ActionEvent event) 59 // 60 { 61 buttonPanel.setBackground(backgroundColor); 62 } 63 } 64 }
1 import java.awt.*; 2 import javax.swing.*; 3 4 /** 5 * @version 1.34 2015-06-12 6 * @author Cay Horstmann 7 */ 8 public class ButtonTest 9 { 10 public static void main(String[] args) 11 { 12 EventQueue.invokeLater(() -> { 13 JFrame frame = new ButtonFrame(); 14 frame.setTitle("ButtonTest");// 15 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 16 frame.setVisible(true); 17 }); 18 } 19 }
l 用lambda表达式简化程序;
1 import java.awt.*; 2 import java.awt.event.*; 3 import javax.swing.*; 4 5 /** 6 * A frame with a button panel 7 */ 8 public class ButtonFrame extends JFrame { 9 private JPanel buttonPanel; 10 private static final int DEFAULT_WIDTH = 300; 11 private static final int DEFAULT_HEIGHT = 200; 12 13 public ButtonFrame() { 14 setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); 15 16 buttonPanel = new JPanel(); 17 18 add(buttonPanel); 19 20 makeButton("yellow",Color.YELLOW); 21 makeButton("blue",Color.BLUE); 22 makeButton("red", Color.RED); 23 makeButton("green", Color.GREEN); 24 25 } 26 27 public void makeButton(String name, Color backgroudColor) { 28 JButton button = new JButton(name); 29 buttonPanel.add(button); 30 ColorAction action = new ColorAction(backgroudColor); 31 button.addActionListener(action); 32 } 33 34 /** 35 * An action listener that sets the panel's background color. 36 */ 37 private class ColorAction implements ActionListener 38 // 定义一个私有类,监听器类对象(ColorAction) 39 { 40 private Color backgroundColor; 41 42 public ColorAction(Color c) { 43 backgroundColor = c; 44 } 45 46 public void actionPerformed(ActionEvent event) 47 // 48 { 49 buttonPanel.setBackground(backgroundColor); 50 } 51 } 52 }
l 掌握JButton组件的基本API;
l 掌握Java中事件处理的基本编程模型。
测试程序2:
l 在elipse IDE中调试运行教材449页程序11-2,结合程序运行结果理解程序;
l 在组件观感设置代码处添加注释;
l 了解GUI程序中观感的设置方法。
1 import javax.swing.JButton; 2 import javax.swing.JFrame; 3 import javax.swing.JPanel; 4 import javax.swing.SwingUtilities; 5 import javax.swing.UIManager; 6 7 /** 8 * A frame with a button panel for changing look-and-feel 9 */ 10 public class PlafFrame extends JFrame 11 { 12 private JPanel buttonPanel; 13 14 public PlafFrame() 15 { 16 buttonPanel = new JPanel(); 17 18 UIManager.LookAndFeelInfo[] infos = UIManager.getInstalledLookAndFeels(); 19 //获得一个用于描述已安装的观感实现的对象数组 20 for (UIManager.LookAndFeelInfo info : infos) 21 makeButton(info.getName(), info.getClassName()); 22 //返回观感的显示名称 返回观感的实现类的名称 23 add(buttonPanel); 24 pack(); 25 } 26 27 /** 28 * Makes a button to change the pluggable look-and-feel. 29 * @param name the button name 30 * @param className the name of the look-and-feel class 31 */ 32 private void makeButton(String name, String className) 33 { 34 // add button to panel 35 36 JButton button = new JButton(name); 37 buttonPanel.add(button); 38 39 // set button action 40 41 button.addActionListener(event -> { 42 // button action: switch to the new look-and-feel 43 try 44 { 45 UIManager.setLookAndFeel(className); 46 //利用给定的类名设置当前的观感 47 SwingUtilities.updateComponentTreeUI(this); 48 pack(); 49 } 50 catch (Exception e) 51 { 52 e.printStackTrace(); 53 } 54 }); 55 } 56 }
1 import java.awt.*; 2 import javax.swing.*; 3 4 /** 5 * @version 1.32 2015-06-12 6 * @author Cay Horstmann 7 */ 8 public class PlafTest 9 { 10 public static void main(String[] args) 11 { 12 EventQueue.invokeLater(() -> { 13 JFrame frame = new PlafFrame(); 14 frame.setTitle("PlafTest"); 15 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 16 frame.setVisible(true); 17 }); 18 } 19 }
运行结果如下:
测试程序3:
l 在elipse IDE中调试运行教材457页-458页程序11-3,结合程序运行结果理解程序;
l 掌握AbstractAction类及其动作对象;
l 掌握GUI程序中按钮、键盘动作映射到动作对象的方法。
1 import java.awt.*; 2 import java.awt.event.*; 3 import javax.swing.*; 4 5 /** 6 * A frame with a panel that demonstrates color change actions. 7 */ 8 public class ActionFrame extends JFrame 9 { 10 private JPanel buttonPanel; 11 private static final int DEFAULT_WIDTH = 300; 12 private static final int DEFAULT_HEIGHT = 200; 13 14 public ActionFrame() 15 { 16 setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); 17 18 buttonPanel = new JPanel(); 19 20 // define actions 21 Action yellowAction = new ColorAction("Yellow", new ImageIcon("yellow-ball.gif"), 22 Color.YELLOW); 23 Action blueAction = new ColorAction("Blue", new ImageIcon("blue-ball.gif"), Color.BLUE); 24 Action redAction = new ColorAction("Red", new ImageIcon("red-ball.gif"), Color.RED); 25 26 // add buttons for these actions 27 buttonPanel.add(new JButton(yellowAction)); 28 buttonPanel.add(new JButton(blueAction)); 29 buttonPanel.add(new JButton(redAction)); 30 31 // add panel to frame 32 add(buttonPanel); 33 34 // associate the Y, B, and R keys with names 35 InputMap imap = buttonPanel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 36 //获得将按键映射到动作键的输入映射 37 imap.put(KeyStroke.getKeyStroke("ctrl Y"), "panel.yellow"); 38 imap.put(KeyStroke.getKeyStroke("ctrl B"), "panel.blue"); 39 imap.put(KeyStroke.getKeyStroke("ctrl R"), "panel.red"); 40 //根据一个便于人们阅读的说明创建一个按键(由空格分隔的字符串序列) 41 // associate the names with actions 42 ActionMap amap = buttonPanel.getActionMap(); 43 //返回关联动作映射键(可以是任意的对象)和动作对象的映射 44 amap.put("panel.yellow", yellowAction); 45 amap.put("panel.blue", blueAction); 46 amap.put("panel.red", redAction); 47 } 48 49 public class ColorAction extends AbstractAction 50 { 51 /** 52 * Constructs a color action. 53 * @param name the name to show on the button 54 * @param icon the icon to display on the button 55 * @param c the background color 56 */ 57 public ColorAction(String name, Icon icon, Color c) 58 { 59 putValue(Action.NAME, name); 60 putValue(Action.SMALL_ICON, icon); 61 putValue(Action.SHORT_DESCRIPTION, "Set panel color to " + name.toLowerCase()); 62 putValue("color", c); 63 //将名/值对放置在动作对象前 64 } 65 66 public void actionPerformed(ActionEvent event) 67 { 68 Color c = (Color) getValue("color"); 69 //返回被存储的名/值对的值 70 buttonPanel.setBackground(c); 71 } 72 } 73 }
1 import java.awt.*; 2 import javax.swing.*; 3 4 /** 5 * @version 1.34 2015-06-12 6 * @author Cay Horstmann 7 */ 8 public class ActionTest 9 { 10 public static void main(String[] args) 11 { 12 EventQueue.invokeLater(() -> { 13 JFrame frame = new ActionFrame(); 14 frame.setTitle("ActionTest"); 15 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 16 frame.setVisible(true); 17 }); 18 } 19 }
运行结果如下:
测试程序4:
l 在elipse IDE中调试运行教材462页程序11-4、11-5,结合程序运行结果理解程序;
l 掌握GUI程序中鼠标事件处理技术。
1 import java.awt.*; 2 import java.awt.event.*; 3 import java.awt.geom.*; 4 import java.util.*; 5 import javax.swing.*; 6 7 /** 8 * A component with mouse operations for adding and removing squares. 9 */ 10 public class MouseComponent extends JComponent 11 { 12 private static final int DEFAULT_WIDTH = 300; 13 private static final int DEFAULT_HEIGHT = 200; 14 15 private static final int SIDELENGTH = 10; 16 private ArrayListsquares; 17 private Rectangle2D current; // the square containing the mouse cursor 18 19 public MouseComponent() 20 { 21 squares = new ArrayList<>(); 22 current = null; 23 24 addMouseListener(new MouseHandler()); 25 addMouseMotionListener(new MouseMotionHandler()); 26 } 27 28 public Dimension getPreferredSize() { return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT); } 29 30 public void paintComponent(Graphics g) 31 { 32 Graphics2D g2 = (Graphics2D) g; 33 34 // draw all squares 35 for (Rectangle2D r : squares) 36 g2.draw(r); 37 } 38 39 /** 40 * Finds the first square containing a point. 41 * @param p a point 42 * @return the first square that contains p 43 */ 44 public Rectangle2D find(Point2D p) 45 { 46 for (Rectangle2D r : squares) 47 { 48 if (r.contains(p)) return r; 49 } 50 return null; 51 } 52 53 /** 54 * Adds a square to the collection. 55 * @param p the center of the square 56 */ 57 public void add(Point2D p) 58 { 59 double x = p.getX(); 60 double y = p.getY(); 61 62 current = new Rectangle2D.Double(x - SIDELENGTH / 2, y - SIDELENGTH / 2, SIDELENGTH, 63 SIDELENGTH); 64 squares.add(current); 65 repaint(); 66 } 67 68 /** 69 * Removes a square from the collection. 70 * @param s the square to remove 71 */ 72 public void remove(Rectangle2D s) 73 { 74 if (s == null) return; 75 if (s == current) current = null; 76 squares.remove(s); 77 repaint(); 78 } 79 80 private class MouseHandler extends MouseAdapter 81 { 82 public void mousePressed(MouseEvent event) 83 { 84 // add a new square if the cursor isn't inside a square 85 current = find(event.getPoint()); 86 //返回事件发生时,事件源组件左上角的坐标x和y,或点的信息 87 if (current == null) add(event.getPoint()); 88 } 89 90 public void mouseClicked(MouseEvent event) 91 { 92 // remove the current square if double clicked 93 current = find(event.getPoint()); 94 if (current != null && event.getClickCount() >= 2) remove(current); 95 //返回与事件关联的鼠标连击次数 96 } 97 } 98 99 private class MouseMotionHandler implements MouseMotionListener 100 { 101 public void mouseMoved(MouseEvent event) 102 { 103 // set the mouse cursor to cross hairs if it is inside 104 // a rectangle 105 106 if (find(event.getPoint()) == null) setCursor(Cursor.getDefaultCursor()); 107 else setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); 108 } 109 110 public void mouseDragged(MouseEvent event) 111 { 112 if (current != null) 113 { 114 int x = event.getX(); 115 int y = event.getY(); 116 117 // drag the current rectangle to center it at (x, y) 118 current.setFrame(x - SIDELENGTH / 2, y - SIDELENGTH / 2, SIDELENGTH, SIDELENGTH); 119 repaint(); 120 } 121 } 122 } 123 }
1 import javax.swing.*; 2 3 /** 4 * A frame containing a panel for testing mouse operations 5 */ 6 public class MouseFrame extends JFrame 7 { 8 public MouseFrame() 9 { 10 add(new MouseComponent()); 11 pack(); 12 } 13 }
1 import java.awt.*; 2 import javax.swing.*; 3 4 /** 5 * @version 1.34 2015-06-12 6 * @author Cay Horstmann 7 */ 8 public class MouseTest 9 { 10 public static void main(String[] args) 11 { 12 EventQueue.invokeLater(() -> { 13 JFrame frame = new MouseFrame(); 14 frame.setTitle("MouseTest"); 15 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 16 frame.setVisible(true); 17 }); 18 } 19 }
运行结果如下:
实验2:结对编程练习
利用班级名单文件、文本框和按钮组件,设计一个有如下界面(图1)的点名器,要求用户点击开始按钮后在文本输入框随机显示2017级网络与信息安全班同学姓名,如图2所示,点击停止按钮后,文本输入框不再变换同学姓名,此同学则是被点到的同学姓名。
图1 点名器启动界面
图2 点名器点名界面
代码编写如下:
1 import java.awt.BorderLayout; 2 import java.awt.Color; 3 import java.awt.Container; 4 import java.awt.event.ActionEvent; 5 import java.awt.event.ActionListener; 6 import java.util.Random; 7 import javax.swing.JButton; 8 import javax.swing.JFrame; 9 import javax.swing.JLabel; 10 import javax.swing.SwingConstants; 11 public class RollCall { 12 JFrame rFrame=new JFrame("随机点名器"); 13 String[] stuName={"王之泰","王颖奇","苏浪浪","王斌龙","马兴德","汪慧和","王艳","冯志霞","王志成","张云飞","王海珍","杨野","张燕","唐月晨","李瑞红","李婷华","赵栋","张季跃","孔维滢","穷吉","狄慧","达拉草","杨其菊","马凯军","陈亚茹","常惠琢","马昕璐", "王玉兰", "白玛次仁", "王瑜", "杨蓉庆", "刘志梅", "周强","李清华","李晓菁","徐思","邹丰蔚","罗松","杨玲","王燕","韩腊梅", "东文财", "焦旭超"}; 14 JLabel name = new JLabel(); 15 JButton btn = new JButton("开始点名"); 16 Random rd = new Random(); 17 public void init() { 18 JLabel jt= new JLabel("随机点名器"); //设置标签居中 19 jt.setHorizontalAlignment(SwingConstants.CENTER); //设置字体大小 20 jt.setFont(new java.awt.Font("随机点名器",1,35)); //设置名字显示的标签居中 21 name.setHorizontalAlignment(SwingConstants.CENTER); //通过匿名类实现Action按钮的监听事件 22 btn.addActionListener(new ActionListener() { 23 24 public void actionPerformed(ActionEvent e) { 25 String a=getRandomName(); 26 //设置name标签的文字 27 name.setText(a); 28 //设置字体 29 name.setFont(new java.awt.Font(a,2,28)); 30 //设置字体颜色 31 name.setForeground(Color.green); 32 } 33 }); 34 //获取JFrame的面板 35 Container p = this.rFrame.getContentPane(); 36 //设置布局方式,我采用的BorderLayout布局 37 p.setLayout(new BorderLayout(3,1)); 38 p.add(jt,BorderLayout.NORTH); 39 //添加姓名标签在中央 40 p.add(name,BorderLayout.CENTER); 41 p.add(btn,BorderLayout.SOUTH); 42 rFrame.pack(); //设置窗体大小 43 rFrame.setSize(250, 250); 44 //设置可以显示 45 rFrame.setVisible(true); 46 } 47 //获取随机的姓名 48 public String getRandomName() { 49 int a = 0; 50 a = rd.nextInt(stuName.length); 51 return stuName[a]; 52 } 53 public static void main(String[] args) { 54 RollCall rn=new RollCall(); 55 rn.init(); 56 } 57 }
运行结果如下:
4. 实验总结:
通过本次实验我掌握了事件处理的基本原理,理解了其用途;掌握了AWT事件模型的工作机制;掌握了事件处理的基本编程模型;了解了GUI界面组件观感设置方法;也掌握了WindowAdapter类、AbstractAction类的用法;还掌握了GUI程序中鼠标事件处理技术。