实验十三 图形界面事件处理技术
实验时间 2018-11-22
1、实验目的与要求
(1) 掌握事件处理的基本原理,理解其用途;
事件源:能够产生事件的对象都可以成为事件源,如文本框、按钮等,一个事件源是一个能够注册监听器并向监听器发送事件对象的对象。
事件监听器:事件监听器对象接收事件源发送的报告(事件对象),并对发生的事件作出响应。一个监听器对象就是一个实现了专门监听器接口的类实例该类必须实现接口中的方法方法当事件发生时就自动执行。
事件对象:java将时间的相关信息封装在一个事件对象中,所有的事件对象都最终派生于java.util.EventObject类。不同的事件源都可以产生不同类别的事件。
(2) 掌握AWT事件模型的工作机制;
监听器对象:是一个实现了特定监听器接口的类实例。
事件源:是一个能够注册监听器对象并发送事件对象的对象。
当事件发生时,事件源将事件对象自动传递给所有注册的监听器。监听器对象利用事件对象中的信息决定如何事件作出响应。
(3) 掌握事件处理的基本编程模型;
注册监听器方法:
eventSourceObject.addEventListener(eventListenerObject)
监听器接口的方法实现:
Class Mylistener implements ActionListener
{
Public void actionforomered(ActionEvent event)
{……}
}
创建按钮对象
JButton类常用的一组构造方法:
JButton(String text)创建一个带文本的按钮。
JButton(Icon icon):创建一个带图标的按钮。
JButton(String text,Icon icon):创建一个带文本和图标的按钮。
按钮对象的常用方法:
getLable():返回按钮的标签字符串;
setLable(String s):设置按钮的标签为字符串s。
(4) 了解GUI界面组件观感设置方法;
String程序设计默认使用Metal观感,采用两种方式改变观感。
第一种:在java安装的子目录下jre/lib下的文件
swing.properties中,将属性swing.defaultlaf设置为所希望的观感类名。
Swing.defaultlaf =
Com.sun.java.swing.plaf.motifLookAndFeel
第二种:调用静态的UIManager.setLookAndFeel方法,动态的改变观感,提供所想要的观感类名,再调用静态方法SwingUtilities.updateComponentTreUI来刷新全部的组件集。
(5) 掌握WindowAdapter类、AbstractAction类的用法;
扩展WindowAdapter类,继承六个空方法,并且覆盖WindowClosing()方法;
class Terminator extends WindowAdapter
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
}
(6) 掌握GUI程序中鼠标事件处理技术。
鼠标事件 MouseEvent
鼠标监听器接口 MouseMotionListener
鼠标监听器适配器 MouseAdapt , MouseMotionAdapter
2、实验内容和步骤
实验1: 导入第11章示例程序,测试程序并进行代码注释。
测试程序1:
l 在elipse IDE中调试运行教材443页-444页程序11-1,结合程序运行结果理解程序;
l 在事件处理相关代码处添加注释;
l 用lambda表达式简化程序;
l 掌握JButton组件的基本API;
l 掌握Java中事件处理的基本编程模型。
ButtonTest
package button; import java.awt.*; import javax.swing.*; /** * @version 1.34 2015-06-12 * @author Cay Horstmann */ public class ButtonTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new ButtonFrame(); frame.setTitle("ButtonTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置默认的关闭操作 frame.setVisible(true);//对图形用户界面进行可视化处理。 }); } }
ButtonFrame
package button; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * A frame with a button panel */ public class ButtonFrame extends JFrame { private JPanel buttonPanel;// private static final int DEFAULT_WIDTH = 300;//宽为300px private static final int DEFAULT_HEIGHT = 200;//长为200px //方法一 //注释掉这个构造器之后只能显示一个窗格,面板上没有内容 /* public ButtonFrame()//构造器 { setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);//决定框架大小 // create buttons 创建按钮 JButton yellowButton = new JButton("Yellow");//Yellow字符串是显示在按钮上的文本 JButton blueButton = new JButton("Blue"); JButton redButton = new JButton("Red"); buttonPanel = new JPanel();//使 buttonPanel指向一个具体的容器对象 // add buttons to panel buttonPanel.add(yellowButton);//将按钮添加到面板中 buttonPanel.add(blueButton); buttonPanel.add(redButton); // add panel to frame add(buttonPanel); // create button actions //生成三个监听器类对象 当事件发生时,事件源将事件对象传递给所有注册的监听器 //颜色值在Color类中,通过类名调用 ColorAction yellowAction = new ColorAction(Color.YELLOW); ColorAction blueAction = new ColorAction(Color.BLUE); ColorAction redAction = new ColorAction(Color.RED); // associate actions with buttons 将操作与按钮相关联 yellowButton.addActionListener(yellowAction); //注释掉之后程序可以运行,点击按钮,背景色不变 blueButton.addActionListener(blueAction); redButton.addActionListener(redAction); }*/ //方法二 /*public ButtonFrame()//构造器 { buttonPanel = new JPanel();//使 buttonPanel指向一个具体的容器对象 setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);//决定框架大小 add(buttonPanel); makeButton("Yellow",Color.YELLOW); makeButton("blue",Color.BLUE); makeButton("red",Color.RED); makeButton("green",Color.GREEN); } public void makeButton(String name,Color BackgroundColor) { JButton button = new JButton(name); buttonPanel.add(button); ColorAction action = new ColorAction(BackgroundColor);//初始化一个颜色对象 button.addActionListener(action);//添加一个事件监听器 }*/ //方法三 /*public ButtonFrame()//构造器 { buttonPanel = new JPanel();//使 buttonPanel指向一个具体的容器对象 setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);//决定框架大小 add(buttonPanel); makeButton("Yellow",Color.YELLOW); makeButton("blue",Color.BLUE); makeButton("red",Color.RED); makeButton("green",Color.GREEN); } public void makeButton(String name,Color BackgroundColor) { JButton button = new JButton(name); buttonPanel.add(button); //使响应用户动作的组件和监听器放在一起 button.addActionListener(new ActionListener() //new之后有一个缺省的类名,之后直接跟了ActionListener接口 匿名内部类 { public void actionPerformed(ActionEvent event) { buttonPanel.setBackground(BackgroundColor); } }); } *//** * An action listener that sets the panel's background color. *//* */ public ButtonFrame()//构造器 { buttonPanel = new JPanel();//使 buttonPanel指向一个具体的容器对象 setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);//决定框架大小 add(buttonPanel); makeButton("Yellow",Color.YELLOW); makeButton("blue",Color.BLUE); makeButton("red",Color.RED); makeButton("green",Color.GREEN); } public void makeButton(String name,Color BackgroundColor) { JButton button = new JButton(name); buttonPanel.add(button); button.addActionListener((background)-> { buttonPanel.setBackground(BackgroundColor); }); } /** * An action listener that sets the panel's background color. */ //监听器类,类名是ColorAction /* private class ColorAction implements ActionListener//实现了一个监听器接口 { private Color backgroundColor; public ColorAction(Color c) { backgroundColor = c; } public void actionPerformed(ActionEvent event) { buttonPanel.setBackground(backgroundColor); } }*/ }
运行结果:
测试程序2:
l 在elipse IDE中调试运行教材449页程序11-2,结合程序运行结果理解程序;
l 在组件观感设置代码处添加注释;
l 了解GUI程序中观感的设置方法。
PlafTest
package plaf; import java.awt.*; import javax.swing.*; /** * @version 1.32 2015-06-12 * @author Cay Horstmann */ public class PlafTest { public static void main(String[] args) { EventQueue.invokeLater(() -> {//lambda表达式 JFrame frame = new PlafFrame();//生成plafFrame类对象 frame.setTitle("PlafTest");//设置框架标题 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置默认的关闭操作 frame.setVisible(true);//对图形用户界面进行可视化处理。 }); } }
PlafFrame
package plaf; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.UIManager; /** * A frame with a button panel for changing look-and-feel */ //使用辅助方法makeButton指定按钮动作,即切换观感。 public class PlafFrame extends JFrame { private JPanel buttonPanel; public PlafFrame() { buttonPanel = new JPanel(); UIManager.LookAndFeelInfo[] infos = UIManager.getInstalledLookAndFeels(); for (UIManager.LookAndFeelInfo info : infos) makeButton(info.getName(), info.getClassName());//得到观感的名字和类名 add(buttonPanel); pack();//调整窗口大小,要考虑其组建的首选大小 } /** * Makes a button to change the pluggable look-and-feel. * 创建一个按钮来更改可插入的外观 * @param name the button name * @param className the name of the look-and-feel class */ private void makeButton(String name, String className) { // add button to panel JButton button = new JButton(name); buttonPanel.add(button); // set button action button.addActionListener(event -> { // button action: switch to the new look-and-feel 按钮动作:切换到新的观感 //加入异常处理技术 try { UIManager.setLookAndFeel(className); SwingUtilities.updateComponentTreeUI(this); pack(); } catch (Exception e) { e.printStackTrace(); } }); } }
运行结果:
测试程序3:
l 在elipse IDE中调试运行教材457页-458页程序11-3,结合程序运行结果理解程序;
l 掌握AbstractAction类及其动作对象;
l 掌握GUI程序中按钮、键盘动作映射到动作对象的方法。
ButtonFrame
package button; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * A frame with a button panel */ public class ButtonFrame extends JFrame { private JPanel buttonPanel; private static final int DEFAULT_WIDTH = 300; private static final int DEFAULT_HEIGHT = 200; public ButtonFrame() { setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); // create buttons 创建按钮 JButton yellowButton = new JButton("Yellow");//括号内是按钮上的文本字符串 JButton blueButton = new JButton("Blue"); JButton redButton = new JButton("Red"); buttonPanel = new JPanel(); // add buttons to panel 将设置好的按钮添加到面板中 buttonPanel.add(yellowButton); buttonPanel.add(blueButton); buttonPanel.add(redButton); // add panel to frame add(buttonPanel);//在框架中添加新的面板 // create button actions 创建按钮动作 改变面板颜色 ColorAction yellowAction = new ColorAction(Color.YELLOW);//颜色值在Color类中,通过类名调用 ColorAction blueAction = new ColorAction(Color.BLUE); ColorAction redAction = new ColorAction(Color.RED); // associate actions with buttons 将操作与按钮相关联 yellowButton.addActionListener(yellowAction); blueButton.addActionListener(blueAction); redButton.addActionListener(redAction); } /** * An action listener that sets the panel's background color. * 设置面板背景色的动作监听器 */ private class ColorAction implements ActionListener//实现了一个监听器接口 { private Color backgroundColor; public ColorAction(Color c) { backgroundColor = c; } public void actionPerformed(ActionEvent event) { buttonPanel.setBackground(backgroundColor); } } }
ButtonTest
package button; import java.awt.*; import javax.swing.*; /** * @version 1.34 2015-06-12 * @author Cay Horstmann */ public class ButtonTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new ButtonFrame(); frame.setTitle("ButtonTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
运行结果:
测试程序4:
l 在elipse IDE中调试运行教材462页程序11-4、11-5,结合程序运行结果理解程序;
l 掌握GUI程序中鼠标事件处理技术。
运行结果:
package mouse; import java.awt.*; import javax.swing.*; /** * @version 1.34 2015-06-12 * @author Cay Horstmann */ public class MouseTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new MouseFrame();//生成一个MouseFrame类对象 frame.setTitle("MouseTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
package mouse; import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import java.util.*; import javax.swing.*; /** * A component with mouse operations for adding and removing squares. * 用于添加和删除方块的具有鼠标操作的组件 */ public class MouseComponent extends JComponent { //设置框架大小
private static final int DEFAULT_WIDTH = 300; private static final int DEFAULT_HEIGHT = 200; private static final int SIDELENGTH = 10;//设置小方块边长为10px private ArrayList<Rectangle2D> squares; private Rectangle2D current; // the square containing the mouse cursor 包含鼠标指针的方块 public MouseComponent() { squares = new ArrayList<>(); current = null; addMouseListener(new MouseHandler()); addMouseMotionListener(new MouseMotionHandler()); } public Dimension getPreferredSize() { return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT); } public void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g; // draw all squares for (Rectangle2D r : squares) g2.draw(r); } /** * Finds the first square containing a point. * @param p a point * @return the first square that contains p */ public Rectangle2D find(Point2D p) { for (Rectangle2D r : squares) { if (r.contains(p)) return r; } return null; } /** * Adds a square to the collection. * @param p the center of the square */ public void add(Point2D p) { double x = p.getX(); double y = p.getY(); current = new Rectangle2D.Double(x - SIDELENGTH / 2, y - SIDELENGTH / 2, SIDELENGTH, SIDELENGTH); squares.add(current); repaint(); } /** * Removes a square from the collection. * @param s the square to remove */ public void remove(Rectangle2D s) { if (s == null) return; if (s == current) current = null; squares.remove(s); repaint(); } private class MouseHandler extends MouseAdapter { public void mousePressed(MouseEvent event) { // add a new square if the cursor isn't inside a square current = find(event.getPoint()); if (current == null) add(event.getPoint()); } public void mouseClicked(MouseEvent event) { // remove the current square if double clicked 如果双击,则删除当前方块 current = find(event.getPoint()); if (current != null && event.getClickCount() >= 2) remove(current); } } private class MouseMotionHandler implements MouseMotionListener { public void mouseMoved(MouseEvent event) { // set the mouse cursor to cross hairs if it is inside // a rectangle if (find(event.getPoint()) == null) setCursor(Cursor.getDefaultCursor()); else setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); } public void mouseDragged(MouseEvent event) { if (current != null) { int x = event.getX(); int y = event.getY(); // drag the current rectangle to center it at (x, y) current.setFrame(x - SIDELENGTH / 2, y - SIDELENGTH / 2, SIDELENGTH, SIDELENGTH); repaint(); } } } }
package mouse; import javax.swing.*; /** * A frame containing a panel for testing mouse operations */ public class MouseFrame extends JFrame { public MouseFrame() { add(new MouseComponent()); pack();
} }
实验2:结对编程练习
利用班级名单文件、文本框和按钮组件,设计一个有如下界面(图1)的点名器,要求用户点击开始按钮后在文本输入框随机显示2017级网络与信息安全班同学姓名,如图2所示,点击停止按钮后,文本输入框不再变换同学姓名,此同学则是被点到的同学姓名。
结对人:白玛次仁
package dianming; import java.util.*; import java.awt.*; import javax.swing.*; import java.awt.event.*; import java.awt.Frame; import java.io.File; import java.io.FileNotFoundException; public class dianmingqi extends JFrame implements ActionListener{ private static final long serialVersionUID = 1L; //serialVersionUID适用于Java的序列化机制,简单来说,Java的序列化机制是通过判断类的 private JButton but ; private JButton show; private static boolean flag = true; public static void main(String arguments []) { new dianmingqi(); } public dianmingqi(){ but = new JButton("开始");//创建一个“开始”按钮 but.setBounds(100,150,100,40); show = new JButton("随机点名");//创建一个“随机点名”按钮 show.setBounds(80,80,180,30); add(but);//将按钮添加到面板中 add(show); setLayout(null); setVisible(true);//面板的可视化处理 setResizable(false); setBounds(100,100,300,300); this.getContentPane().setBackground(Color.white);//面板背景色为白色 setTitle("点名");//设置框架标题 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭该面板 but.addActionListener(this); } public void actionPerformed(ActionEvent e){ int i=0; String names[]=new String[50];//创建一个数组,大小为50 try { Scanner in=new Scanner(new File("D:\studentnamelist.txt"));//将文件写入程序 while(in.hasNextLine()) { names[i]=in.nextLine();//读取文件,遍历全班姓名 i++; } } catch (FileNotFoundException e1) { e1.printStackTrace();//异常处理 } //点击开始后的操作 if(but.getText()=="开始"){ show.setBackground(Color.gray); flag=true; new Thread(){ public void run(){ while(dianmingqi.flag){ Random r = new Random(); //随机点名 int i= r.nextInt(43); show.setText(names[i]); } } }.start(); but.setText("停止"); but.setBackground(Color.darkGray); } else if(but.getText()=="停止"){ flag = false; but.setText("开始"); but.setBackground(Color.WHITE); show.setBackground(Color.magenta); } } }
运行结果:
总结:本周主要学习了事件处理,也同时综合了上一章的内容。前三个程序看起来比较容易理解,最后一个关于鼠标的有一点看不懂,自己动手编程的话就感觉很难,失败了好多次。主要是平时不加以练习的原因。还需要继续学习。