0

0

详解JAVA事件处理机制

零下一度

零下一度

发布时间:2017-06-25 10:38:39

|

2428人浏览过

|

来源于php中文网

原创

我们连续写了两小节的教师-学生的例子,必然觉得无聊死了,这样的例子我们就是玩上100遍,还是不知道该怎么写真实的代码。那从本节开始,我们开始往真实代码上面去靠拢。

事件最容易理解的例子是鼠标事件:我们点击鼠标,鼠标发送指令,执行代码。

 

一:鼠标点击事件处理模型基础版

这个时候,我们必须去查看下JDK中相关类型。对照着上一节《从零开始理解JAVA事件处理机制(2)》中的UML图,我们很快发现,对应HomeworkListener,JDK中有MouseListener,其实我们靠分析也能得知,MouseListener继承自EventListener。现在既然有了接口MouseListener了,那我们必定会有一个实现类,这个类假设叫做:ConcreteMouseListener。不妨先实现之:

立即学习Java免费学习笔记(深入)”;

package com.zuikc.events;import java.awt.event.MouseEvent;import java.awt.event.MouseListener;public class ConcreteMouseListener implements MouseListener {    public ConcreteMouseListener(){    }    @Override    public void mouseClicked(MouseEvent e) {        System.out.printf("我被{%s}点了一下,MD痒死了~~", e.getSource().toString());    }    @Override    public void mousePressed(MouseEvent e) {        // TODO Auto-generated method stub    }    @Override    public void mouseReleased(MouseEvent e) {        // TODO Auto-generated method stub    }    @Override    public void mouseEntered(MouseEvent e) {        // TODO Auto-generated method stub    }    @Override    public void mouseExited(MouseEvent e) {        // TODO Auto-generated method stub    }}

我们为单击的事件处理器添加业务代码。

事件处理器:监听器的具体实现类的实现方法,就叫事件处理器。

接下来要看什么,当然是MouseEvent。MouseEvent,这个JDK中的类相对来说,就稍微有点大了,起构造方法的参数有点多,不过没有关系呀,我们慢慢看,我先说这个类要怎么用,即怎么new出来。

/*
* 这里的new Component() {} 就是 event.getSource() 得到的事件源 source
*/
MouseEvent event = new MouseEvent(new Component() {}, 1, 1, 1,2,3,4,false);

在实际且正常的情况下,MouseEvent是没有必要自己new的,JAVA运行时会捕获硬件鼠标的点击动作,由虚拟机底层为我们生成该实例对象(下文会为我们分析这一点),但是我们此时此刻我们是先模拟呀,所以不妨碍我们自己胡乱new一个出来。注意,new不是问题,问题的关键我们必须知道其构造器参数的意义,而其中核心关键参数就是第一个参数,new Component(),这是什么?这就是那个事件源!回头看看我们的教师学生版本是在哪里生产事件的:

    public void setHomework(String homework) {
        System.out.printf("%s布置了作业%s \n", this.name, homework);
        homeworks.add(homework);
        HomeworkEventObject event = new HomeworkEventObject(this);
        /*
         * 在观察者模式中,我们直接调用Observable的notifyObservers来通知被观察者
         * 现在我们只能自己通知了~~
         */
        for (HomeworkListener listener : homeworkListenerList) {
            listener.update(event, homework);
        }

    }

是在Teacher的业务代码setHomework中。所以,在当前的我们要写的这个例子中,new MouseEvent要在哪里呢?我们在Button的业务代码中,Button是谁,Button就类似Teacher,但又不完全等同Teacher,在Teacher中,Teacher本身就是事件源,所以它这个this作为参数传入进了HomeworkEventObject,而Button不能作为参数传入进MouseEvent,因为我不打算让Button继承自Component,所以我们先new了一个临时的Component。OK,分析到了这里,我们自己的Button代码大概就出来了,是这个样子的:

package com.zuikc.events;

import java.awt.AWTEvent;
import java.awt.AWTEventMulticaster;
import java.awt.Component;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.peer.LightweightPeer;

public class Button {
    private MouseListener mouseListener;
    public void addMouseListener(MouseListener l) {
        mouseListener = l;
    }
    public void doClick(){
        /*
         * 这里的new Component() {} 就是 event.getSource() 得到的事件源 source
         */
        MouseEvent event = new MouseEvent(new Component() {}, 1, 1, 1,2,3,4,false);
        //event.getSource();
        this.mouseListener.mouseClicked(event);
    }
}

至此,我们可以画出清晰的类图了,来看:

image

顺便我们看一下Client端的代码:

public static void main(String[] args) {
    ConcreteMouseListener listener = new ConcreteMouseListener();
    Button button = new Button();
    button.addMouseListener(listener);
    button.doClick();
}

运行一下吧,你应该得到一句类似这样的输出:

我被{com.zuikc.events.Button$1[,0,0,0x0,invalid]}点了一下,MD痒死了~~

 

二,一个正常的窗体程序的样子

上面,我们尽量偏向于教师学生的例子,写出了鼠标事件的基础版本,但是说好的程序本来的样子呢?来,我们接下来写个正常的程序,99.9%在人在写窗体程序的时候就是如下这么写的。我知道你们又会有人上来骂了,什么,java,窗体程序?我TMD学JAVA是为了EE开发的,企业开发的。现在,我们先说好不好互相伤害,要知道,即便是NB如JAVA,最先也是先从窗体发迹的,并且,JAVA的窗体框架推倒重写了还不止一次。所以,窗体的事件你明白了,EE中那些框架的事件碰到了简直跟切白菜一样。

言归正传,看代码:

package com.zuikc.events;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JButton;
import javax.swing.JFrame;

public class Client {
    public static void main(String[] args) {
        new DemoFrame();
    }
}

class DemoFrame extends JFrame implements MouseListener {

    public DemoFrame() {
        super("demo");
        this.setSize(500, 400);
        this.setLocationRelativeTo(null);
        this.getContentPane().setLayout(null);
        this.setVisible(true);

        JButton button1 = new JButton("ok");
        button1.setBounds(8, 8, 80, 80);
        button1.addMouseListener(this);
        this.getContentPane().add(button1);
    }

Win32 API函数手册 chm版
Win32 API函数手册 chm版

Win32_API_函数详解查询手册 chm格式,分为限制程序功能函数、注册表处理函数、对话框函数、时间处理函数、磁盘处理函数、进程函数、文件处理函数、断点设置列表等相关内容。

下载

    @Override
    public void mouseClicked(MouseEvent e) {
        System.out.printf("我被{%s}点了一下,MD痒死了~~", e.getSource().toString());
    }

    @Override
    public void mousePressed(MouseEvent e) {
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }
}

这段代码什么意思?最简单了,就是创建了一个窗体,窗体上放置了一个按钮,点击了之后,执行了一行代码。这简简单单的一个文件,没多少行代码,实际上就实现了我们上文中一堆类中实现的功能。来吧,我们分析吧,把监听器、事件处理器、事件、事件源都指出来。

监听器:DemoFrame就是监听器,对应ConcreteMouseListener;

事件处理器:MouseClicked方法就是监听器,ConcreteMouseListener里面也有这个方法;

事件:看不到了,怎么办?

事件源:看不到了,怎么办?

注意,窗体本身就监听器,所以上文代码中为button添加监听器怎么做?button1.addMouseListener(this);没错,就是把自身添加进去。

然后,事件和事件源都看不到了,这个时候怎么办?我们如果看输出的话,上文代码的输出为:

我被{javax.swing.JButton[,8,8,80x80,invalid,alignmentX=0.0,alignmentY=0.5,border=javax.swing.plaf.BorderUIResource$CompoundBorderUIResource@7fda7dfe,flags=296,maximumSize=,minimumSize=,preferredSize=,defaultIcon=,disabledIcon=,disabledSelectedIcon=,margin=javax.swing.plaf.InsetsUIResource[top=2,left=14,bottom=2,right=14],paintBorder=true,paintFocus=true,pressedIcon=,rolloverEnabled=true,rolloverIcon=,rolloverSelectedIcon=,selectedIcon=,text=ok,defaultCapable=true]}点了一下,MD痒死了~~

看上去,类似我们上文第一部分代码的输出,也是JButton业务代码运行过程中生成的一个变量,但它是在哪里生成的,在哪里产生的,我们并不知道。不过没关系,我们看调试堆栈!

一步步的往上追,我们终于追到了这里:

 

image

由此可见,MouseEvent也是在业务代码里new出来了,大家可能要为,那这个重要的第一个参数target呢?target可是事件源也很重要,道理很简单,往上继续追,限于篇幅,这里不在展开,它在某个你愿意看到它的地方被new出来了。

现在我们补齐回答,

事件:JAVA运行时捕获到硬件鼠标触发,从而调用了事件处理器,在事件处理器内部生成的这个MouseEvent,就是事件;

事件源:JAVA运行时捕获到硬件鼠标触发,从而调用了事件处理器,在事件处理器内部生成的这个target,就是事件源;

 

三:正常版的上文第一部分的代码

按照二中的代码来写,我们第一部分的代码应该是什么样子的呢?

一和二放在一起比较,其实只要改两个地方,一中的代码就和二中完全一致了,

1:将ConcreteMouseListener命名为DemoFrame;

2:将Button实例由客户端放置到ConcreteMouseListener内部;

OK,事件就是这么简单。

该系列的第一部分和第二部分分别在:

1:从零开始理解JAVA事件处理机制(1)

2:从零开始理解JAVA事件处理机制(2)

相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

34

2026.01.14

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

14

2026.01.13

PHP 高性能
PHP 高性能

本专题整合了PHP高性能相关教程大全,阅读专题下面的文章了解更多详细内容。

34

2026.01.13

MySQL数据库报错常见问题及解决方法大全
MySQL数据库报错常见问题及解决方法大全

本专题整合了MySQL数据库报错常见问题及解决方法,阅读专题下面的文章了解更多详细内容。

18

2026.01.13

PHP 文件上传
PHP 文件上传

本专题整合了PHP实现文件上传相关教程,阅读专题下面的文章了解更多详细内容。

12

2026.01.13

PHP缓存策略教程大全
PHP缓存策略教程大全

本专题整合了PHP缓存相关教程,阅读专题下面的文章了解更多详细内容。

6

2026.01.13

jQuery 正则表达式相关教程
jQuery 正则表达式相关教程

本专题整合了jQuery正则表达式相关教程大全,阅读专题下面的文章了解更多详细内容。

3

2026.01.13

交互式图表和动态图表教程汇总
交互式图表和动态图表教程汇总

本专题整合了交互式图表和动态图表的相关内容,阅读专题下面的文章了解更多详细内容。

44

2026.01.13

nginx配置文件详细教程
nginx配置文件详细教程

本专题整合了nginx配置文件相关教程详细汇总,阅读专题下面的文章了解更多详细内容。

5

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 2.5万人学习

C# 教程
C# 教程

共94课时 | 6.7万人学习

Java 教程
Java 教程

共578课时 | 45.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号