201871010134-周英杰《面向对象程序设计(java)》第十三周学习总结
项目 |
内容 |
这个作业属于哪个课程 |
https://www.cnblogs.com/nwnu-daizh/ |
这个作业的要求在哪里 |
https://www.cnblogs.com/nwnu-daizh/p/11888568.html |
作业学习目标 |
(1) 掌握事件处理的基本原理,理解其用途; (2) 掌握AWT事件模型的工作机制; (3) 掌握事件处理的基本编程模型; (4) 了解GUI界面组件观感设置方法; (5) 掌握WindowAdapter类、AbstractAction类的用法; (6) 掌握GUI程序中鼠标事件处理技术。
|
一·理论知识
(1) 掌握事件处理的基本原理,理解其用途;
事件源(event source):能够产生事件的对象都可 以成为事件源,如文本框、按钮等。一个事件源是一个 能够注册监听器并向监听器发送事件对象的对象。事件监听器(event listener):事件监听器对象接 收事件源发送的通告(事件对象),并对发生的事件作 出响应。一个监听器对象就是一个实现了专门监听器接 口的类实例,该类必须实现接口中的方法,这些方法当 事件发生时,被自动执行。事件对象(event object):Java将事件的相关信息 封装在一个事件对象中,所有的事件对象都最终派生于 java.util.EventObject类。不同的事件源可以产生不 同类别的事件。
(2) 掌握AWT事件模型的工作机制;
一、常用术语
GUI(Graphics user interface)图形用户接口
CLI (Command line user interface)命令行用户接口
Java为GUI提供的类。
java.awt (Abstract Window Toolkit)抽象工具包。重量级控件
javax.swing 轻量级控件
二、布局管理器
1、FlowLayout,流式,从左到右,默认居中
2、BorderLayout,边界,上北north,下南south,左西west,右东east,中心center。默认
3、GridLayout ,网格,规则矩阵
4、CardLayou 卡片布局
5、GirdBagLayou 网格包,非规则矩阵
三、常用方法
类 Component常用方法:
显示:
void setVisible(boolean b)
根据参数 b 的值显示或隐藏此组件。
大小:
void setSize(Dimension d)
调整组件的大小,使其宽度为 d.width,高度为 d.height。
void setSize(int width, int height)
调整组件的大小,使其宽度为 width,高度为 height。
位置:
void setLocation(int x, int y)
将组件移到新位置。
Window类:
位置:
void setBounds(int x, int y, int width, int height)
移动组件并调整其大小。
四、事件监听机制
1、事件源
能够产生事件的对象都可以成为事件源,如文本框,按钮等。也就是说,事件源必须是一个对象,
而且这个对象必须是Java认为能够发生时间的对象。
2,监听器(Listener)
需要一个对象对事件源进行监视,以便对发生的事件作出处理。
例如:对于文本框,这个方法为:addActionListener(监视器);
3,处理事件的接口
监视器负责处理事件源发生的事件。为了让监视器这个对象能对事件源发生的事件进行处理,
创建该监视器对象的类必须申明实现相应的接口,即必须在类体中给出该接口中的所有方法体,
那么当事件源发生事件时,监视器就自动调用类实现的某个接口方法。
(3) 掌握事件处理的基本编程模型;
1.事件类型——侦听程序接口
系统将这些用户事件分类,分成各种事件类型。
系统为每个事件类型提供了一个侦听程序接口,接口包含的方法,规定了接受并处理该类事件的规范。
2.侦听程序接口——事件侦听程序
为了接收并处理某个事件类型,组件必须注册相应的事件处理程序,称为事件侦听程序(Listener,也称为侦听器)。
Listener的构造条件有两个:
一是必须实现对应事件类型的侦听程序接口,
二是需要实现接口中规定的响应事件的方法。
例如,为了处理按钮上的ActionEvent事件,需要定义一个实现ActionListener接口的侦听程序类。
public interface ActionListener extends EventListener{
public void actionPerformed(ActionEvent e);
}
该接口中只定义了一个方法actionPerformed(),当出现ActionEvent事件时,就会调用该方法。
actionPerformed(),是一个回调函数。即被系统调用的函数。
直调回调的差别在于,调用主体是不是第一人称的程序体。actionPerformed()是预先设定的函数,但是设定当时并没有被调用,而是等待ActionEvent发生时候,由系统来把这种行为作为参数,调用这个函数。
btw,系统调用这些回调的方法是轮询,即用轮询的方式在线程池队列中查找侦听这个系统事件的回调函数。
我们回到这个侦听事件类。每个组件都有若干个形如addXXXListener(XXXListener)的方法,通过这类方法,可以为组件注册事件侦听程序。
这种处理事件机制称为委托事件处理机制。
概括地说,事件被直接送往产生这个事件的组件,组件需要注册一个或多个侦听程序。侦听程序的类中包含了事件处理程序,接收和处理这个事件。事件是一个对象,它只向注册的侦听程序报告。
(4) 了解GUI界面组件观感设置方法;
wing程序默认使用Metal观感,采用两种方式改变观感。
第一种:在Java安装的子目录jre/1ib下的文件sw ing. properties中,将属性swing. defaultlaf设置为所希望的观感类名。
swing.defaultlaf =com.sun.java. swing.plaf.motif.MotifL ookAndFeel
第二种:调用静态的UIManager. setLookAndFee1方法动态地改变观感,提供所想要的观感类名,再调用静态方法SwingUtiliti es. updateComponentTreeUI来刷新全部的组件集。
(5) 掌握WindowAdapter类、AbstractAction类的用法;
WindowAdapter类:
1.接收窗口事件的抽象适配器类。此类中的方法为空。此类存在的目的是方便创建侦听器对象。
2.扩展此类可创建 WindowEvent
侦听器并为所需事件重写该方法。(如果要实现 WindowListener
接口,则必须定义该接口内的所有方法。此抽象类将所有方法都定义为 null,所以只需针对关心的事件定义方法。)
3.使用扩展的类可以创建侦听器对象,然后使用窗口的 addWindowListener
方法向该窗口注册侦听器。当通过打开、关闭、激活或停用、图标化或取消图标化而改变了窗口状态时,将调用该侦听器对象中的相关方法,并将 WindowEvent
传递给该方法。
AbstractAction类的简单认识 :
AbstractAction类是Action接口的抽象实现。AbstractAction为Action接口中的大多数方法提供了默认功能,我们可以扩展AbstractAction类来建立自定义的特定动作。由此,必须为接口的实现提供唯一的方法:actionPerformed()方法。
(6) 掌握GUI程序中鼠标事件处理技术。
Java语言支持用户通过鼠标与应用程序进行交互。程序可以检测鼠标并对鼠标操作中发生的变化作出反应。。鼠标事件通过MouseListener接口处理,并通过如下方法对事件反应。
mouseClicked:点击事件,当点击和释放鼠标按钮时处理此事件。
mouseEntered:当鼠标进入一个组件时处理此事件。
mouseExitied:当鼠标离开组件时处理此事件。
mousePressed:当鼠标按下时处理此事件。
mouseReleased:当鼠标释放时处理此事件。
二·实验部分
试验一:
代码部分:
import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * 带有按钮的面板框架 */ 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); buttonPanel = new JPanel(); makeButton("yellow",Color.YELLOW); makeButton("yellow",Color.BLUE); makeButton("yellow",Color.RED); makeButton("yellow",Color.GREEN); add(buttonPanel); } public void makeButton(String name,Color backgroundColor) { JButton button =new JButton(name); buttonPanel.add(button); button.addActionListener(event -> buttonPanel.setBackground(backgroundColor)); } }
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(() ->//lambda表达式 { JFrame frame = new ButtonFrame(); frame.setTitle("ButtonTest");//标题 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true);//可见 }); } }
运行结果:
实验二:
实验代码;
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(() -> { JFrame frame = new PlafFrame(); frame.setTitle("PlafTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.UIManager; /** * 带有按钮面板的框架,用于更改外观和感觉 */ 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(); } /** * 创建一个按钮来更改可插入的外观. * @param name the button name * @param className the name of the look-and-feel class */ private void makeButton(String name, String className) { //添加按钮到面板 JButton button = new JButton(name); buttonPanel.add(button); //设置按钮要进行的操作 button.addActionListener(event -> { // 按钮操作结果: 切换到新的外观 try //可能出错的代码放入try子句中 { UIManager.setLookAndFeel(className); SwingUtilities.updateComponentTreeUI(this); pack(); } catch (Exception e) { e.printStackTrace(); } }); } }
运行结果;
实验三:
实验代码:
import java.awt.*; import javax.swing.*; /** * @version 1.34 2015-06-12 * @author Cay Horstmann */ public class ActionTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { var frame = new ActionFrame(); frame.setTitle("ActionTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * A frame with a panel that demonstrates color change actions. */ public class ActionFrame extends JFrame { private JPanel buttonPanel; private static final int DEFAULT_WIDTH = 300; private static final int DEFAULT_HEIGHT = 200; public ActionFrame() { setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); buttonPanel = new JPanel(); // define actions var yellowAction = new ColorAction("Yellow", new ImageIcon("yellow-ball.gif"), Color.YELLOW); var blueAction = new ColorAction("Blue", new ImageIcon("blue-ball.gif"), Color.BLUE); var redAction = new ColorAction("Red", new ImageIcon("red-ball.gif"), Color.RED); // add buttons for these actions buttonPanel.add(new JButton(yellowAction)); buttonPanel.add(new JButton(blueAction)); buttonPanel.add(new JButton(redAction)); // add panel to frame add(buttonPanel); // associate the Y, B, and R keys with names InputMap inputMap = buttonPanel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); inputMap.put(KeyStroke.getKeyStroke("ctrl Y"), "panel.yellow"); inputMap.put(KeyStroke.getKeyStroke("ctrl B"), "panel.blue"); inputMap.put(KeyStroke.getKeyStroke("ctrl R"), "panel.red"); // associate the names with actions ActionMap actionMap = buttonPanel.getActionMap(); actionMap.put("panel.yellow", yellowAction); actionMap.put("panel.blue", blueAction); actionMap.put("panel.red", redAction); } public class ColorAction extends AbstractAction { /** * Constructs a color action. * @param name the name to show on the button * @param icon the icon to display on the button * @param c the background color */ public ColorAction(String name, Icon icon, Color c) { putValue(Action.NAME, name); putValue(Action.SMALL_ICON, icon); putValue(Action.SHORT_DESCRIPTION, "Set panel color to " + name.toLowerCase()); putValue("color", c); } public void actionPerformed(ActionEvent event) { var color = (Color) getValue("color"); buttonPanel.setBackground(color); } } }
运行结果:
实验四:
实验代码;
import javax.swing.*; /** * A frame containing a panel for testing mouse operations */ public class MouseFrame extends JFrame { public MouseFrame() { add(new MouseComponent()); pack(); } }
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(); frame.setTitle("MouseTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import java.util.*; import javax.swing.*; /** * 用于添加和删除方块的具有鼠标操作的组件 */ 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; private ArrayList<Rectangle2D> squares; private Rectangle2D current; // 包含鼠标光标的正方形 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; //画出所有方块 for (Rectangle2D r : squares) g2.draw(r); } /** * 找到第一个包含点的正方形. * @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; } /** * 向集合中添加一个正方形. * @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(); } /** * 从集合中移除一个正方形. * @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) { // 如果光标不在正方形内,则添加一个新的正方形 current = find(event.getPoint()); if (current == null) add(event.getPoint()); } public void mouseClicked(MouseEvent event) { // 如果双击,则删除当前方块 current = find(event.getPoint()); if (current != null && event.getClickCount() >= 2) remove(current); } } private class MouseMotionHandler implements MouseMotionListener { public void mouseMoved(MouseEvent event) { // 如果鼠标指针在内部,则将其设置为十字线 // 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(); // 拖动当前矩形到(x, y)的中心 current.setFrame(x - SIDELENGTH / 2, y - SIDELENGTH / 2, SIDELENGTH, SIDELENGTH); repaint(); } } } }
运行结果:
实验五:
结对编程:
利用班级名单文件、文本框和按钮组件,设计一个有如下界面(图1)的点名器,要求用户点击开始按钮后在文本输入框随机显示2018级计算机科学与技术(1)班同学姓名,如图2所示,点击停止按钮后,文本输入框不再变换同学姓名,此同学则是被点到的同学姓名,如图3所示。
结对编程思路:
我们先设计了一个GUI图形界面,然后将学生信息读取后存储带一个数组当中,在实现监听器类actionPerformed方法时,采用随机数下标获取学生信息数组中的值,再重写timer类的schedule类中的run方法实现定时器功能。当button中的内容为“开始”时,启动定时器,当button中的内容为“停止”时,则调用timer类对象的cancel方法停用定时器,这样就完成了对点名器的代码编程。
实验代码;
import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Label; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.Timer; public class Rollcall { public static void main(String args[]) { try { Dmq dmq = new Dmq(); dmq.lab.setText("随机点名器"); dmq.setTitle("点名器"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } class Dmq extends JFrame { final Label lab = new Label(); ArrayList<String> namelist = new ArrayList<String>(); public Dmq() throws IOException { File file = new File("D:/JAVA/2019studentlist.txt"); FileInputStream fis = new FileInputStream(file); InputStreamReader isr = new InputStreamReader(fis, "UTF-8"); BufferedReader br = new BufferedReader(isr); String line = ""; while ((line = br.readLine()) != null) { if (line.lastIndexOf("---") < 0) { namelist.add(line); } } setBounds(550, 270, 500, 300); final Timer timer = new Timer(50, new ActionListener() { public void actionPerformed(ActionEvent e) { lab.setText(namelist.get((int) (Math.random() * namelist.size()))); lab.setBackground(Color.YELLOW); } }); JButton jbutton = new JButton("开始"); jbutton.setPreferredSize(new Dimension(80,60)); jbutton.setBackground(Color.green); jbutton .setFont(new java.awt.Font("华文行楷", 1, 22)); jbutton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JButton jbutton = (JButton) e.getSource(); if (jbutton.getText().equals("开始")) { jbutton.setText("停止"); timer.start(); } else if (jbutton.getText().equals("停止")) { jbutton.setText("开始"); timer.stop(); } } }); jbutton.setBounds(30, 30, 300, 100); lab.setBackground(new Color(200, 200, 200)); this.setLayout(new FlowLayout()); this.add(lab); this.add(jbutton); this.setBackground(Color.green); this.setSize(400, 250); this.setVisible(true); this.setDefaultCloseOperation(EXIT_ON_CLOSE); br.close(); } }
运行结果:
结对编程照片:
实验总结:
不得不说,这几天上的java内容我非常喜欢,非常喜欢,非常喜欢,重要的是说三遍,我本就喜欢做那种做完马上就能看见成果的的事,而最近java做完马上就能看到成果,可能还有一个方面,就是人机交互可能更加友好了,所以就喜欢了。本周可以说是收获最大的一周,比以前好多了。这次我学到了事件处理的基本原理,理解其用途;AWT事件模型的工作机制;大致了解了事件处理的基本编程模型;了解GUI界面组件观感设置方法;掌握WindowAdapter类、AbstractAction类的用法;掌握了GUI程序中鼠标事件处理技术。下一周的要加油,我能行的,我一定行。