首页 Java java教程 详解JAVA事件处理机制

详解JAVA事件处理机制

Jun 25, 2017 am 10:38 AM
java 事件 处理 开始 理解

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

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

 

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

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

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

    @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事件处理机制的详细内容。更多信息请关注PHP中文网其他相关文章!

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

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前 By 尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

Java 中的平方根 Java 中的平方根 Aug 30, 2024 pm 04:26 PM

Java 中的平方根指南。下面我们分别通过例子和代码实现来讨论平方根在Java中的工作原理。

Java 中的完美数 Java 中的完美数 Aug 30, 2024 pm 04:28 PM

Java 完美数指南。这里我们讨论定义,如何在 Java 中检查完美数?,示例和代码实现。

Java 中的随机数生成器 Java 中的随机数生成器 Aug 30, 2024 pm 04:27 PM

Java 随机数生成器指南。在这里,我们通过示例讨论 Java 中的函数,并通过示例讨论两个不同的生成器。

Java中的Weka Java中的Weka Aug 30, 2024 pm 04:28 PM

Java 版 Weka 指南。这里我们通过示例讨论简介、如何使用weka java、平台类型和优点。

Java 中的阿姆斯特朗数 Java 中的阿姆斯特朗数 Aug 30, 2024 pm 04:26 PM

Java 中的阿姆斯特朗数指南。这里我们讨论一下java中阿姆斯特朗数的介绍以及一些代码。

Java 中的史密斯数 Java 中的史密斯数 Aug 30, 2024 pm 04:28 PM

Java 史密斯数指南。这里我们讨论定义,如何在Java中检查史密斯号?带有代码实现的示例。

Java Spring 面试题 Java Spring 面试题 Aug 30, 2024 pm 04:29 PM

在本文中,我们保留了最常被问到的 Java Spring 面试问题及其详细答案。这样你就可以顺利通过面试。

突破或从Java 8流返回? 突破或从Java 8流返回? Feb 07, 2025 pm 12:09 PM

Java 8引入了Stream API,提供了一种强大且表达力丰富的处理数据集合的方式。然而,使用Stream时,一个常见问题是:如何从forEach操作中中断或返回? 传统循环允许提前中断或返回,但Stream的forEach方法并不直接支持这种方式。本文将解释原因,并探讨在Stream处理系统中实现提前终止的替代方法。 延伸阅读: Java Stream API改进 理解Stream forEach forEach方法是一个终端操作,它对Stream中的每个元素执行一个操作。它的设计意图是处

See all articles