201871010105-曹玉中《面向对象程序设计(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程序中鼠标事件处理技术。

第一部分:理论知识

一、Java的事件处理机制

二、事件处理流程

1、给事件源对象注册监听者

事件监听者是在事件发生时要对事件进行处理的对象。AWT定义了各种类型的事件,每一种事件有相应的事件监听者接口 ,在接口中描述了处理相应事件应该实现的基本行为。若事件类名为XxxEvent,则事件监听接口的命名为XxxListener,给部件注册监听者的方法为addXxxListener(XxxListener a)。
    列子:只要用户点击按钮,JButton对象就会创建一个ActionEvent对象,然后调用listener.actionPerformed(event)传递事件对象。

内嵌类的方法:
MyListener listener = new MyListener();
JButton button = new JButton("OK");
button.addActionListener(listener);
class MyListener implements ActionListener{
...
public void actionPerformed(ActionEvent event){
...
}
}

 

lambda 表达式:
exitButton.addActionListener(event -> Systeu.exit(O));
使用匿名类:
exitButton.addActionListener(new ActionListener()
{
public void actionPerformed(new ActionEvent)
{
System.exit(0);
}
});

  

2、给监听者编写事件处理代码

3、发生事件时调用监听者的方法进行相关处理
    java的事件处理机制称为委托事件处理,事件源发生事件时由监听者处理。监听者中定义事件处理方法,事件源不需要实现任何接口,但其内部有个列表记录该事件源注册了哪些监听者,从而保证发生事件时能去调用监听者的方法。

三、适配器类adapter:

鉴于简化的目的,每个含有 多个方法的 AWT 监听器接口都配有一个适配器(XxxAdapter) 类,这个类实现了接口中的所有方 法, 但每个方法没有做任何事情。可以通过继承适配器类来指定对某些事件的响应动作,而不必实现接口中的每 个方法(ActionListener 这样的接口只有一个方法,因此没必要提供适配器类)。

内部类方法:
class Terminator extends WindowAdapter
{
public void windowCIosing(WindowEvent e)
{
if {useragrees) System.exit(O);
}
}
frame.addWindowListener(new Terminator());

  

匿名内部类方法:
frame.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
if (useragrees) System.exit(0);
}
});

四、动作

通常, 激活一个命令可以有多种方式。用户可以通过菜单、击键或工具栏上的按钮选择 特定的功能。在 AWT 事件模型中实现这些非常容易:将所有事件连接到同一个监听器上。
    Swing包提供了一种非常实用的机制来封装命令,并将它们连接到多个事件源,这就是 Action 接口。
    有一个类实现了这个接口除 actionPerformed 方法之外的所有方 法,它就是 AbstractAction。这个类存储了所有名 / 值对, 并管理着属性变更监听器。我们可 以直接扩展 AbstractAction 类,并在扩展类中实现 actionPerformed方法。

五、AWT事件继承层次

AWT事件类的继承关系图

事件处理总结:

AWT将事件分为底层low-level)事件和语义semantic)事件。语义事件是表示用户动作的事件,底层事件是形成那些事件的事件。
 下面是 java.awt.event 包中最常用的语义事件类:
  •ActionEvent (对应按钮点击、 菜单选择、选择列表项或在文本框中 ENTER);  
  •AdjustmentEvent (用户调节滚动条);
  •ItemEvem (用户从复选框或列表框中选择一项)。
常用的 5 个底层事件类是:
  •KeyEvent (一个键被按下或释放);
  •MouseEvent (鼠标键被按下、 释放、 移动或拖动);
  •MouseWheelEvent (鼠标滚轮被转动);
  •FocusEvent (某个组件获得焦点或失去焦点);
  •WindowEvent ( 窗口状态被改变)

所有的Listener接口都继承于EventListener,位于java.util包中。

第二部分:实验

实验1: 导入第11章示例程序,测试程序并进行代码注释。

测试程序1:

● 在elipse IDE中调试运行教材443页-444页程序11-1,结合程序运行结果理解程序;

● 在事件处理相关代码处添加注释;

● 用lambda表达式简化程序;

● 掌握JButton组件的基本API;

● 掌握Java中事件处理的基本编程模型。

代码如下:

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); // 创建了三个按钮对象
var yellowButton = new JButton("Yellow");
var blueButton = new JButton("Blue");
var redButton = new JButton("Red");
//创建了一个面板对象
buttonPanel = new JPanel(); //将三个按钮添加到面板中
buttonPanel.add(yellowButton);
buttonPanel.add(blueButton);
buttonPanel.add(redButton); // add panel to frame
add(buttonPanel); // create button actions
var yellowAction = new ColorAction(Color.YELLOW);
var blueAction = new ColorAction(Color.BLUE);
var redAction = new ColorAction(Color.RED); // 将动作和按钮联系起来
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);
}
}
}

  

package button;

import java.awt.*;
import javax.swing.*; /**
* @version 1.35 2018-04-10
* @author Cay Horstmann
*/
public class ButtonTest
{
public static void main(String[] args)
{
EventQueue.invokeLater(() -> {
var frame = new ButtonFrame();
frame.setTitle("ButtonTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
}

  运行结果如下:

简化后的代码:

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);
buttonPanel = new JPanel();
makeButton("yellow", Color.yellow);
makeButton("blue", Color.blue);
makeButton("red", Color.red);
add(buttonPanel); } protected void makeButton(String name,Color backgound) {
// create buttons
JButton button = new JButton(name);
// add buttons to panel
buttonPanel.add(button);
button.addActionListener((e)->{
buttonPanel.setBackground(backgound);
}); }
}

  运行结果如下:

测试程序2:

● 在elipse IDE中调试运行教材449页程序11-2,结合程序运行结果理解程序;

● 在组件观感设置代码处添加注释;

● 了解GUI程序中观感的设置方法。

代码如下:

package button;

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();
}
});
}
}

  

package button;

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);
});
}
}

  运行结果如下:

测试程序3:

● 在elipse IDE中调试运行教材457页-458页程序11-3,结合程序运行结果理解程序;

● 掌握AbstractAction类及其动作对象;

● 掌握GUI程序中按钮、键盘动作映射到动作对象的方法。

代码如下:

package action;

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(); // 定义动作
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(buttonPanel); // 将Y,B,R这些键与名称联系起来
/*
*可以使用getInputMap方法从组件中得到输入映射
* WHEN_ANCESTOR_OF_FOCUSED_COMPONENT条件意味着在当前组件包含了拥有键盘焦点的组件时会查看这个映射
*/
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)
{
//将所有信息存储在AbstractAction类提供的名/值对表中
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)
{
//获取名/值对表中名为color的值并将其强制转换为颜色对象
var color = (Color) getValue("color");
buttonPanel.setBackground(color);
}
}
}

  

package action;

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);
});
}
}

  运行结果如下:

测试程序4:

● 在elipse IDE中调试运行教材462页程序11-4、11-5,结合程序运行结果理解程序;

● 掌握GUI程序中鼠标事件处理技术。

代码如下:

package mouse;

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)
{
var g2 = (Graphics2D) g; // 遍历正方形集合,并将每个正方形绘制出来
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)
{
//如果光标所在位置在正方形集合中包含并且鼠标点击次数>=2,则删除此位置的正方形
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(); // 拖动当前矩形使其居中(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();
}
}

  

package mouse;

import java.awt.*;
import javax.swing.*; /**
* @version 1.35 2018-04-10
* @author Cay Horstmann
*/
public class MouseTest
{
public static void main(String[] args)
{
EventQueue.invokeLater(() -> {
var frame = new MouseFrame();
frame.setTitle("MouseTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
}

  运行结果如下:

实验2:结对编程练习

利用班级名单文件、文本框和按钮组件,设计一个有如下界面(图1)的点名器,要求用户点击开始按钮后在文本输入框随机显示2018级计算机科学与技术(1)班同学姓名,如图2所示,点击停止按钮后,文本输入框不再变换同学姓名,此同学则是被点到的同学姓名。

代码如下:

package chart13;
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 ButtonFrame 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 ButtonFrame(); } public ButtonFrame(){ but = new JButton("START");//创建一个“开始”按钮
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.black);//面板背景色为白色
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:\\student.txt"));//将文件写入程序
while(in.hasNextLine())
{
names[i]=in.nextLine();//读取文件,遍历全班姓名
i++;
}
} catch (FileNotFoundException e1) { e1.printStackTrace();//异常处理
} //点击开始后的操作
if(but.getText()=="START"){ show.setBackground(Color.GREEN);
flag=true;
new Thread(){
public void run(){
while(ButtonFrame.flag){
Random r = new Random(); //随机点名
int i= r.nextInt(43);
show.setText(names[i]);
}
}
}.start();
but.setText("STOP");
but.setBackground(Color.BLUE);
}
else if(but.getText()=="STOP"){
flag = false;
but.setText("START");
but.setBackground(Color.WHITE);
show.setBackground(Color.magenta);
}
} }

  运行结果如下:

学习总结:

通过本章的学习,了解了如何对事件进行处理,比如通过点击按钮或者鼠标对界面进行操控,通过实验课上学长演示实验,再用lambda表达式以及匿名类等简化程序,

使得自己对实验有了更多的了解。第一部分的验证理解实验难度相对较小一点,但在结对编程的过程中出现了较多的问题,也是通过借助他人力量完成本次实验,希望

学长和老师能够详细讲解一下结对编程部分内容,以便有更深刻的理解。

201871010105-曹玉中《面向对象程序设计(java)》第十三周学习总结的更多相关文章

  1. 201771010134杨其菊《面向对象程序设计java》第九周学习总结

                                                                      第九周学习总结 第一部分:理论知识 异常.断言和调试.日志 1.捕获 ...

  2. 201871010132-张潇潇《面向对象程序设计(java)》第一周学习总结

    面向对象程序设计(Java) 博文正文开头 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cn ...

  3. 扎西平措 201571030332《面向对象程序设计 Java 》第一周学习总结

    <面向对象程序设计(java)>第一周学习总结 正文开头: 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 ...

  4. 杨其菊201771010134《面向对象程序设计Java》第二周学习总结

    第三章 Java基本程序设计结构 第一部分:(理论知识部分) 本章主要学习:基本内容:数据类型:变量:运算符:类型转换,字符串,输入输出,控制流程,大数值以及数组. 1.基本概念: 1)标识符:由字母 ...

  5. 201871010124 王生涛《面向对象程序设计JAVA》第一周学习总结

    项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://edu.cnblogs.com/campus/xbsf/ ...

  6. 201871010115——马北《面向对象程序设计JAVA》第二周学习总结

    项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...

  7. 201777010217-金云馨《面向对象程序设计(Java)》第二周学习总结

    项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...

  8. 201871010132——张潇潇《面向对象程序设计JAVA》第二周学习总结

    项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...

  9. 201771010123汪慧和《面向对象程序设计Java》第二周学习总结

    一.理论知识部分 1.标识符由字母.下划线.美元符号和数字组成, 且第一个符号不能为数字.标识符可用作: 类名.变量名.方法名.数组名.文件名等.第二部分:理论知识学习部分 2.关键字就是Java语言 ...

  10. 201521123061 《Java程序设计》第十三周学习总结

    201521123061 <Java程序设计>第十三周学习总结 1. 本周学习总结 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jm ...

随机推荐

  1. 快速获取 IP 地址

    IP 地址可以分为两类,公用和私有(专用).公用 IP 是唯一的 IP 地址,可以从 Internet 访问.专用 IP 地址保留供您专用网络内部使用,而不会直接暴露给 Internet. 本文将介绍 ...

  2. SQL Server 迁移数据库 (三)使用SQL脚本

    1. 创建脚本 1.1 在需要迁移的数据库上右击>Tasks>Generate Scrips 1.2 前两步直接Next,第三步我这里选择Save to Clipboard,因为如果选Sa ...

  3. Codeforces Round #553 (Div. 2) E 贡献

    https://codeforces.com/contest/1151/problem/E 题意 一条长n的链,每个点上有值\(a[i]\),定义\(f(l,r)\)为该区间的\(值\)所代表的点留下 ...

  4. 小白专场-堆中的路径-c语言实现

    目录 一.题意理解 二.堆的表示及其操作 三.主程序 更新.更全的<数据结构与算法>的更新网站,更有python.go.人工智能教学等着你:https://www.cnblogs.com/ ...

  5. 数据仓库005 - 复习Linux shell命令 - crontab调度 sh脚本 后台执行 软连接

    一.crontab调度 对于linux 自带crontab而言,      xxx.sh的一般编写格式以#!/bin/bash 解释器开头,可在脚本中加入: date 但是,shell脚本执行 需要 ...

  6. LeetCode 141:环形链表 Linked List Cycle

    给定一个链表,判断链表中是否有环. 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始). 如果 pos 是 -1,则在该链表中没有环. Given a l ...

  7. 洛谷 P2656 (缩点 + DAG图上DP)

    ### 洛谷 P2656 题目链接 ### 题目大意: 小胖和ZYR要去ESQMS森林采蘑菇. ESQMS森林间有N个小树丛,M条小径,每条小径都是单向的,连接两个小树丛,上面都有一定数量的蘑菇.小胖 ...

  8. docker安装和配置Grafana

    目录 安装 docker 启动 配置 配置域名和端口 配置ldap 配置邮箱 添加数据源 创建dashboard 配置alert 安装 docker 启动 先普通启动,然后把配置文件导出来,修改配置文 ...

  9. C#,File.AppendAllLines(),换行"\r\n"

    string sourcePath = @"D:\GL\20160826141915999999.txt"; for (int i = 0; i < 10; i++) { G ...

  10. 分享windows 10 下部署 elasticsearch 和 logstash (二)

    接上一篇,es部署很简单,很快就弄好了. 但是还是有很多不玩美. 比如说:主机是本地的IP或机器名,端口是固定的9200. 而且是只有一个节点,我要在一台机器上部署多个节点呢. 经过一段时间的摸索,做 ...