精华内容
下载资源
问答
  • event
    千次阅读
    2022-01-14 13:06:08

    Pygame Event事件模块(详细示例)

    事件(Event)是 Pygame 的重要模块之一,它是构建整个游戏程序的核心,比如鼠标点击、键盘敲击、游戏窗口移动、调整窗口大小、触发特定的情节、退出游戏等等,这些都可以看做是“事件”,Pygame 会接受用户产生的各种操作(或事件),这些操作随时产生,并且操作量可大可小,那么 Pygame 是如何处理这些事件的呢?

    事件类型

    Pygame 定义了一个专门用来处理事件的结构,即事件队列,该结构遵循遵循队列“先到先处理”的基本原则,通过事件队列,我们可以有序的、逐一的处理用户的操作(触发事件)。下述表格列出了 Pygame 中常用的游戏事件:

    事件类型 描述 成员属性

    QUIT 用户按下窗口的关闭按钮 none

    ATIVEEVENT Pygame被激活或者隐藏 gain,state

    KEYDOWN 键盘按下 unicode、key、mod

    KEYUP 键盘放开 key、mod

    MOUSEMOTION 鼠标移动 pos, rel, buttons

    MOUSEBUTTONDOWN 鼠标按下 pos, button

    MOUSEBUTTONUP 鼠标放开 pos, button

    JOYAXISMOTION 游戏手柄(Joystick or pad) 移动 joy, axis, value

    JOYBALLMOTION 游戏球(Joy ball) 移动 joy, axis, value

    JOYHATMOTION 游戏手柄(Joystick) 移动 joy, axis, value

    JOYBUTTONDOWN 游戏手柄按下 joy, button

    JOYBUTTONUP 游戏手柄放开 joy, button

    VIDEORESIZE Pygame窗口缩放 size, w, h

    VIDEOEXPOSE Pygame窗口部分公开(expose) none

    USEREVENT 触发一个用户事件 事件代码

    注意,当使用 Pygame 做游戏开发时,上述事件并非都会应用的到,因此在学习的过程中,我们要懂得触类旁通、举一反三。

    事件处理方法

    Pygame.event 模块提供了处理事件队列的常用方法,如下表所示:

    方法 说明

    pygame.event.get() 从事件队列中获取一个事件,并从队列中删除该事件

    pygame.event.wait() 阻塞直至事件发生才会继续执行,若没有事件发生将一直处于阻塞状态

    pygame.event.set_blocked() 控制哪些事件禁止进入队列,如果参数值为None,则表示禁止所有事件进入

    pygame.event.set_allowed() 控制哪些事件允许进入队列

    pygame.event.pump() 调用该方法后,Pygame 会自动处理事件队列

    pygame.event.poll() 会根据实际情形返回一个真实的事件,或者一个None

    pygame.event.peek() 检测某类型事件是否在队列中

    pygame.event.clear() 从队列中清除所有的事件

    pygame.event.get_blocked() 检测某一类型的事件是否被禁止进入队列

    pygame.event.post() 放置一个新的事件到队列中

    pygame.event.Event() 创建一个用户自定义的新事件

    当我们使用 Pygame 处理事件时,逻辑一般都是相似的。首先是判断事件的类型,然后根据不同的事件操作,执行不同的游戏操作。因此这种情况非常适合使用 if … else 语句。如下所示:

    while True:
        #等待事件发生
        event = pygame.event.wait()
        if event.type == pygame.QUIT:
            exit()
        if event.type == pygame.MOUSEBUTTONDOWN:
            print('鼠标按下',event.pos)
        if event.type == pygame.MOUSEBUTTONUP:
            print('鼠标弹起')
        if event.type == pygame.MOUSEMOTION:
            print('鼠标移动')
            # 键盘事件
        if event.type ==pygame.KEYDOWN:
            # 打印按键的英文字符
            print('键盘按下',chr(event.key))
        if event.type == pygame.KEYUP:
            print('键盘弹起')
    
    ....
    

    下面应用上述方法对鼠标事件和键盘事件分别做简单的介绍。

    处理键盘事件

    键盘事件会涉及到大量的按键操作,比如游戏中的上下左右,或者人物的前进、后退等操作,这些都需要键盘来配合实现。

    键盘事件提供了一个 key 属性,通过该属性可以获取键盘的按键。Pygame 将键盘上的字母键、数字键、组合键等按键以常量的方式进行了定义,下表列出了部分常用按键的常量:

    常量名 描述

    K_BACKSPACE 退格键(Backspace)

    K_TAB 制表键(Tab)

    K_CLEAR 清除键(Clear)

    K_RETURN 回车键(Enter)

    K_PAUSE 暂停键(Pause)

    K_ESCAPE 退出键(Escape)

    K_SPACE 空格键(Space)

    K_0…K_9 0…9

    K_a…Kz a…z

    K_DELETE 删除键(delete)

    K_KP0…K_KP9 0(小键盘)…9(小键盘)

    K_F1…K_F15 F1…F15

    K_UP 向上箭头(up arrow)

    K_DOWN 向下箭头(down arrow)

    K_RIGHT 向右箭头(right arrow)

    K_LEFT 向左箭头(left arrow)

    KMOD_ALT 同时按下Alt键

    下面通过“图片移动”示例来了解键盘事件的处理过程,如下所示:

    import pygame
    import sys
    # 初始化pygame
    pygame.init()
    # 定义变量
    size = width, height = 600, 400
    bg = (255, 255, 255)
    # 加载logo图
    img = pygame.image.load("C:/Users/Administrator/Desktop/logo.jpg")
    # 获取图像的位置
    position = img.get_rect()
    # 创建一个主窗口
    screen = pygame.display.set_mode(size)
    # 标题
    pygame.display.set_caption("C语言中文网")
    # 创建游戏主循环
    while True:
        # 设置初始值
        site = [0, 0]
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            # 图像移动 KEYDOWN 键盘按下事件
            # 通过 key 属性对应按键
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    site[1] -= 8
                if event.key == pygame.K_DOWN:
                    site[1] += 8
                if event.key == pygame.K_LEFT:
                    site[0] -= 8
                if event.key == pygame.K_RIGHT:
                    site[0] += 8
        # 移动图像
        position = position.move(site)
        # 填充背景
        screen.fill(bg)
        # 放置图片
        screen.blit(img, position)
        # 更新显示界面
        pygame.display.flip()
    

    处理鼠标事件

    鼠标是计算机最重要外接设备之一,同时它也是游戏玩家必不可少的工具之一。

    Pygame 提供了三个鼠标事件,分别是鼠标移动
    (MOUSEMOTION)、鼠标按下(MOUSEBUTTONDOWN)、鼠标释放(MOUSEBUTTONUP),不同事件类型对应着不同的成员属性。如下所示:

    pygame.event.MOUSEMOTION鼠标移动事件

    event.pos 相对于窗口左上角,鼠标的当前坐标值(x,y)
    event.rel 鼠标相对运动距离(X,Y),相对于上次事件
    event.buttons 鼠标按钮初始状态(0,0,0),分别对应(左键,滑轮,右键),移动过程中点击那个键,相应位置变会为1
    

    pygame.event.MOUSEBUTTONUP鼠标键释放事件

    event.pos 相对于窗口左上角,鼠标的当前坐标值(x,y)
    event.button 鼠标释放键编号(整数)左键为1,按下滚动轮2、右键为3
    

    pygame.event.MOUSEBUTTONDOWN 鼠标键按下事件

    event.pos 相对于窗口左上角,鼠标的当前坐标值(x,y)
    event.button 鼠标按下键编号(整数),左键为1,按下滚动轮2、右键为3,向前滚动滑轮4、向后滚动滑轮5
    

    通过一组简单的示例对鼠标事件进行演示,示例代码如下:

    import pygame
    from random import randint
    # 初始化程序
    pygame.init()
    screen = pygame.display.set_mode((450,400))
    pygame.display.set_caption("c语言中文网")
    # 更新显示
    pygame.display.flip()
    while True:
        #等待事件发生
        event = pygame.event.wait()
        if event.type == pygame.QUIT:
            exit("成功退出")
        if event.type == pygame.MOUSEBUTTONDOWN:
            # pos 获取鼠标当前位置
            print('鼠标按下',event.pos)
            mx,my = event.pos
            # 调用 pygame.draw 模块画圆
            pygame.draw.circle(screen,(255,255,0),(mx,my),50)
            # 处理完,更新显示
            pygame.display.update()
        if event.type == pygame.MOUSEBUTTONUP:
            print('鼠标弹起')
            pass
        if event.type == pygame.MOUSEMOTION:
            print('鼠标移动')
            mx, my = event.pos
            # 随机生成 RGB 颜色值
            r = randint(0,255)
            g = randint(0,255)
            b = randint(0,255)
            pygame.draw.circle(screen, (r,g,b,),(mx, my), 50)
            # 处理完,更新显示
            pygame.display.update()
    
    更多相关内容
  • MySQL定时任务(EVENT|事件)如何配置,必会技能!

    千次阅读 多人点赞 2020-11-20 17:30:31
    当为on completion preserve 的时候,当event到期了,event会被disable,但是该event还是会存在 当为on completion not preserve的时候,当event到期的时候,该event会被自动删除掉. ENABLE、DISABLE、DISABLE ON SLAVE ...

      国庆过后我们客户领导换了,这哥们儿好像特别喜欢看各类统计、报告(过眼瘾?),加了二十多个统计数据报告的需求,就好像报告多就会显得很牛逼一样🙃🙃~

      (上线后据我观察操作日志,发现上线后再也没人看报告。。西内!!🔨🔨)

      搞得我最近一直在写定时任务,之前我一直是用SpringTask做定时任务的,还得来回调数据库浪费资源效率。机缘巧合让我发现了MySQL的EVENT(事件),一用才知道MySQL的定时任务竟如此方便,我玩儿了五年MySQL竟然还没用过,还一直以为自己是大腿。。。唉,玻璃心碎了!
      我赶紧深入研究一下,给兄弟们分享一波。嘘!记得偷偷学会,日后让公司同事刮目相看哦~

    在这里插入图片描述

    一、事件(EVENT)是干什么的

      自MySQL5.1.6起,增加了一个非常有特色的功能 - 事件调度器(Event Scheduler),可以用做定时执行某些特定任务(例如:删除记录、数据统计报告、数据备份等等),来取代原先只能由操作系统的计划任务来执行的工作。
      值得一提的是MySQL的事件调度器可以精确到每秒钟执行一个任务,而操作系统的计划任务(如:Linux的cron)只能精确到每分钟执行一次。对于一些对数据实时性要求比较高的应用(例如:股票、赔率、比分等)就非常适合。

      事件有时也可以称为临时触发器(temporal triggers),因为事件调度器是基于特定时间周期触发来执行某些任务,而触发器(Triggers)是基于某个表所产生的事件触发的,区别也就在这里。

    二、开启“事件”功能

    使用“事件”功能之前必须确保event_scheduler已开启

    1、查询功能是否开启:

    -- 方法一
    SELECT @@event_scheduler;
    -- 方法二
    SHOW VARIABLES LIKE 'event%';
    

    显示 “ON”说明功能已开启;如下图:

    mysql> SELECT @@event_scheduler;
    +-------------------+
    | @@event_scheduler |
    +-------------------+
    | ON                |
    +-------------------+
    1 row in set (0.00 sec)
    
    mysql> SHOW VARIABLES LIKE 'event%';
    +-----------------+-------+
    | Variable_name   | Value |
    +-----------------+-------+
    | event_scheduler | ON    |
    +-----------------+-------+
    1 row in set (0.00 sec)
    

    2、开启、关闭功能命令:

    -- 开启功能命令:
    SET GLOBAL event_scheduler = 1;
    SET GLOBAL event_scheduler = ON;
    -- 关闭功能命令:
    SET GLOBAL event_scheduler = 0;
    SET GLOBAL event_scheduler = OFF;
    

    当然,通过命令开启当数据库重启后会自动关闭;

    持久化开启方式:将event_scheduler=1写到my.cnf配置文件中;如下图:

    在这里插入图片描述

    常用的事件操作命令:

    • 关闭指定事件: ALTER EVENT 事件名称 ON COMPLETION PRESERVE DISABLE;
    • 开启指定事件:ALTER EVENT 事件名称 ON COMPLETION PRESERVE ENABLE;
    • 查看当前事件:SHOW EVENTS ;

    三、事件 - SQL语法创建

    下面是EVENT事件创建语句,乍一看挺复杂的,让我们拆开解读一下

    CREATE EVENT [IFNOT EXISTS] event_name
           ON SCHEDULE schedule(调度时间设置)
           [ON COMPLETION [NOT] PRESERVE]
           [ENABLE | DISABLE | DISABLE ON SLAVE]
           [COMMENT 'comment']
           DO sql_statement;
    
    SQL语法说明
    DEFINER可选项,给指定用户使用权限
    IF NOT EXISTS可选项,用于判断要创建的事件是否存在
    EVENT event_name必选项,指定事件名称,event_name的最大长度为64个字符,如果为指定event_name,则默认为当前的MySQL用户名(不区分大小写)
    ON SCHEDULE schedule必选项,这里的schedule用于定义执行的时间和时间间隔,在下面我们详细讲解
    ON COMPLETION [NOT] PRESERVE可选项,配置事件执行完一次后的处理方式;
    当为on completion preserve 的时候,当event到期了,event会被disable,但是该event还是会存在
    当为on completion not preserve的时候,当event到期的时候,该event会被自动删除掉.
    ENABLE、DISABLE、DISABLE ON SLAVE可选项,用于指定事件的一种属性。
    ENABLE表示该事件是开启的,也就是调度器检查事件是否必选调用;
    DISABLE表示该事件是关闭的,也就是事件的声明存储到目录中,但是调度器不会检查它是否应该调用;
    DISABLE ON SLAVE表示事件在从机中是关闭的。如果不指定这三个选择中的任意一个,则在一个事件创建之后,它立即变为活动的。
    COMMENT ‘comment’可选项,用于定义事件的注释
    DO event_body必选项,用于指定事件启动时所要执行的代码。可以是任何有效的SQL语句、存储过程或者一个计划执行的事件。如果包含多条语句,可以使用BEGIN…END复合结构

    schedule 调度时间配置语法:调度时间配置包括ATEVERY两种

    AT timestamp [+ INTERVAL interval] ...
      | EVERY interval
        [STARTS timestamp [+ INTERVAL interval] ...]
        [ENDS timestamp [+ INTERVAL interval] ...]
    
    
    -- INTERVAL中包含的时间单位如下:
    {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE |
     WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE |
     DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}
    

    1、创建 - 单次定时执行事件

    AT TIMESTAMP 时间字符串 [+ INTERVAL INTERVAL]

      AT TIMESTAMP表示该事件只执行一次,TIMESTAMP表示一个具体的时间点,后面可以加上一个时间间隔,表示在这个时间间隔后事件发生。[+ INTERVAL INTERVAL]表示延迟触发时间;

      需要注意的是,TIMESTAMP和具体字符串连用,如果不是具体字符串(如CURRENT_TIMESTAMP取当前时间等),则不加TIMESTAMP;

    • 示例 1:往demo_1119表中插入一行数据,执行时间:2020-11-20 00:00:00
    CREATE EVENT demo_event2 
    ON SCHEDULE AT TIMESTAMP '2020-11-20 00:00:00' 
    DO INSERT INTO `demo_1119` (`id`, `name`, `createTime`) VALUES (null, '陈哈哈', NOW())
    

    结果查询:

    mysql> select * from demo_1119;
    +-----+-----------+---------------------+
    | id  | name      | createTime          |
    +-----+-----------+---------------------+
    | 145 | 陈哈哈    | 2020-11-20 00:00:00 |
    +-----+-----------+---------------------+
    9 rows in set (0.00 sec)
    
    • 示例 2:往demo_1119表中插入一行数据,执行时间:当前时间往后5个小时;
    CREATE EVENT demo_event2 
    ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 5 HOUR
    DO INSERT INTO `demo_1119` (`id`, `name`, `createTime`) VALUES (null, '陈哈哈', NOW())
    

    2、创建 - 循环定时执行事件

    EVERY INTERVAL [STARTS TIMESTAMP] [ENDS TIMESTAMP]

    EVERY表示循环执行该事件,其中STARTS子句用于指定开始时间;ENDS子句用于指定结束时间。

    • 示例 1:从当前开始,每10秒往demo_1119表中插入一行数据
    CREATE EVENT demo_event3 
    ON SCHEDULE EVERY 10 SECOND 
    ON COMPLETION PRESERVE 
    DO INSERT INTO `demo_1119` (`id`, `name`, `createTime`) VALUES (null, '陈哈哈', NOW())
    
    mysql> select * from demo_1119;
    +-----+-----------+---------------------+
    | id  | name      | createTime          |
    +-----+-----------+---------------------+
    | 145 | 陈哈哈    | 2020-11-19 11:10:39 |
    | 146 | 陈哈哈    | 2020-11-19 11:10:49 |
    | 147 | 陈哈哈    | 2020-11-20 11:10:59 |
    | 148 | 陈哈哈    | 2020-11-20 11:11:09 |
    | 149 | 陈哈哈    | 2020-11-20 11:11:19 |
    | 150 | 陈哈哈    | 2020-11-20 11:11:29 |
    | 151 | 陈哈哈    | 2020-11-20 11:11:39 |
    +-----+-----------+---------------------+
    9 rows in set (0.00 sec)
    
    • 示例 2:从2020-11-20 12:00:00开始,每10分钟往demo_1119表中插入一行数据
    CREATE EVENT demo_event4 
    ON SCHEDULE EVERY 10 MINUTE STARTS '2020-11-20 12:00:00' 
    ON COMPLETION PRESERVE 
    DO INSERT INTO `demo_1119` (`id`, `name`, `createTime`) VALUES (null, '陈哈哈', NOW())
    
    mysql> select * from demo_1119;
    +-----+-----------+---------------------+
    | id  | name      | createTime          |
    +-----+-----------+---------------------+
    | 152 | 陈哈哈    | 2020-11-20 12:00:00 |
    | 153 | 陈哈哈    | 2020-11-20 12:10:00 |
    | 154 | 陈哈哈    | 2020-11-20 12:20:00 |
    | 155 | 陈哈哈    | 2020-11-20 12:30:00 |
    | 156 | 陈哈哈    | 2020-11-20 12:40:00 |
    +-----+-----------+---------------------+
    5 rows in set (0.00 sec)
    
    • 示例 3:从当前时间一小时后开始,每10分钟往demo_1119表中插入一行数据;已经测试过可用,我就不再贴冗余查询的数据咯~
    CREATE EVENT demo_event5 
    ON SCHEDULE EVERY 10 MINUTE STARTS CURRENT_TIMESTAMP+INTERVAL 1 HOUR 
    ON COMPLETION PRESERVE 
    DO INSERT INTO `demo_1119` (`id`, `name`, `createTime`) VALUES (null, '陈哈哈', NOW())
    

    示例4:从当前时间一天后开始,每1小时往demo_1119表中插入一行数据,三天后结束

    CREATE EVENT demo_event5 
    ON SCHEDULE EVERY 1 HOUR 
    STARTS CURRENT_TIMESTAMP+INTERVAL 1 DAY 
    ENDS CURRENT_TIMESTAMP+INTERVAL 3 DAY 
    ON COMPLETION PRESERVE 
    DO INSERT INTO `demo_1119` (`id`, `name`, `createTime`) VALUES (null, '陈哈哈', NOW())
    

    示例5:每天零点定时清一下demo_1119表数据

    CREATE EVENT demo_event5 
    ON SCHEDULE EVERY 1 DAY STARTS '2020-11-20 00:00:00' 
    ON COMPLETION PRESERVE 
    DO TRUNCATE table `demo_1119`
    

    3、修改事件

    修改事件语句跟创建语句如出一辙,语法如下:

    ALTER EVENT event_name
           [ONSCHEDULE schedule]
           [old_NAME TO new_NAME]
           [ON COMPLETION [NOT] PRESERVE]
           [COMMENT 'comment']
           [ENABLE | DISABLE]
           [DO sql_statement]
    
    • 关闭事件任务: ALTER EVENT 事件名称 ON COMPLETION PRESERVE DISABLE;
    • 开启事件任务:ALTER EVENT 事件名称 ON COMPLETION PRESERVE ENABLE;

    4、删除事件

    DROP EVENT [IF EXISTS] event_name
    

    四、事件 - 用Navicat创建(推荐)

      很多小伙伴喜欢在命令行敲SQL语句,会有种专业感,但也可能是被领导道德绑架了~~

      就像有些领导们觉得自己员工用Google就很cool😎😎,很带劲;用百度查 csdn 就很 low。 但作为菜狗的我还是喜欢用我的Navicat小工具和度娘。好了废话不多说,我们来看看Navicat是如何创建EVENT事件的,GO!

      如下图,右键点击创建新的事件
    在这里插入图片描述
      创建事件中的定义一栏是写执行SQL的,可以包括一条或多条SQL语句、存储过程等,计划一栏是定义事件触发时间的。如下图,我在执行过程中定义了一条插入语句。

    在这里插入图片描述

    当然也可以同时写多条SQL,中间带分号。以BEGIN开头,END结尾即可。

    在这里插入图片描述

    打开计划栏,是不是觉得很熟悉!在上个模块我们都见过。为了使小伙伴们加深印象,我们在回顾一下吧。

    在这里插入图片描述
    参数说明:

    • AT:表示该事件只执行一次,可以设置一个具体的时间,也可以如图中CURRENT_TIMESTAMP代表当前时间,后面可以加上一个时间间隔interval,表示在这个时间多久以后后事件发生,表示延迟触发时间;

    • EVERY:循环执行该事件,其中STARTS子句用于指定开始时间;ENDS子句用于指定结束时间。

    • interval表示从现在开始时间延迟多久以后的一个时间点,其值由一个数值和单位构成。例如,使用“4 WEEK”表示4周后;使用“‘1:10’ HOUR_MINUTE”表示1小时10分钟后。间隔的距离用DATE_ADD()函数来支配。

    INTERVAL中包含的时间单位如下:

    YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE | WEEK | SECOND |
    YEAR_MONTH | DAY_HOUR | DAY_MINUTE |
    DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND


    好了,让我们通过一些实例来加深印象:
    • 示例 1:往demo_1119表中插入一行数据,执行时间:2020-11-20 00:00:00
      在这里插入图片描述
    • 示例 2:往demo_1119表中插入一行数据,执行时间:当前时间往后5个小时;

    在这里插入图片描述

    • 示例 3:从当前开始,每10秒往demo_1119表中插入一行数据

    在这里插入图片描述

    • 示例 4:从2020-11-20 12:00:00开始,每10分钟往demo_1119表中插入一行数据
      在这里插入图片描述

    • 示例 5:从当前时间一小时后开始,每10分钟往demo_1119表中插入一行数据;
      在这里插入图片描述

    • 示例 6:从当前时间一天后开始,每1小时往demo_1119表中插入一行数据,三天后结束
      在这里插入图片描述

    • 示例 7:每天零点定时清一下demo_1119表数据
      在这里插入图片描述

    附、一张有故事的照片(十)

    在这里插入图片描述

    这段话让我看到了自己的影子,也看到了很多同龄人的影子。


    记得,给你的孩子一个美好的童年 !

    展开全文
  • pygame.event 用于处理事件与事件队列的 Pygame 模块。 函数 pygame.event.pump()—让 Pygame 内部自动处理事件 pygame.event.get()—从队列中获取事件 pygame.event.poll()—从队列中获取一个事件 pygame....

    pygame.event

    用于处理事件与事件队列的 Pygame 模块。

    函数

    • pygame.event.pump()  —  让 Pygame 内部自动处理事件
    • pygame.event.get()  —  从队列中获取事件
    • pygame.event.poll()  —  从队列中获取一个事件
    • pygame.event.wait()  —  等待并从队列中获取一个事件
    • pygame.event.peek()  —  检测某类型事件是否在队列中
    • pygame.event.clear()  —  从队列中删除所有的事件
    • pygame.event.event_name()  —  通过 id 获得该事件的字符串名字
    • pygame.event.set_blocked()  —  控制哪些事件禁止进入队列
    • pygame.event.set_allowed()  —  控制哪些事件允许进入队列
    • pygame.event.get_blocked()  —  检测某一类型的事件是否被禁止进入队列
    • pygame.event.set_grab()  —  控制输入设备与其他应用程序的共享
    • pygame.event.get_grab()  —  检测程序是否共享输入设备
    • pygame.event.post()  —  放置一个新的事件到队列中
    • pygame.event.Event()  —  创建一个新的事件对象
    • pygame.event.EventType  —  代表 SDL 事件的 Pygame 对象

    Pygame 通过事件队列控制所有的时间消息。该模块中的程序将帮你管理事件队列。输入队列很大程度依赖于 pygame 的 display 模块。如果 display 没有被初始化,显示模式没有被设置,那么事件队列就还没有开始真正工作。

    常规的队列是由 pygame.event.EventType 定义的事件对象的组成,有多种方法来访问里边的事件对象:从简单的检测事件是否存在,到直接从栈中获取它们。

    所有事件都有一个类型标识符,这个标识符对应的值定义在 NOEVENT 到 NUMEVENTS 之间(温馨提示:类似于 C 语言的宏定义,明白?)。用户可以自行定义事件,但类型标识符的值应该高于或等于 USEREVENT。

    获取各种输入设备的状态,推荐你直接通过它们相应的模块(mouse,key 和 joystick)提供的函数访问,而不是通过事件队列; 如果你使用此函数,请记住,Pygame 需要通过一些方式与系统的窗口管理器和平台的其他部分进行通信。为了保持 Pygame 和系统同步,你需要调用 pygame.event.pump() 确保实时更新,你将在游戏的每次循环中调用这个函数。

    事件队列提供了一些简单的过滤。通过阻止某些事件进入事件队列,可以略微提高游戏的性能(温馨提示:因为这样事件队列的尺寸就会小一些,所以说可以略微提升性能)。使用 pygame.event.set_allowed() 和 pygame.event.set_blocked() 来控制某些事件是否允许进入事件队列。默认所有事件都会进入事件队列。

    事件子系统应该在主线程被调用。如果你希望从其他线程中投递事件消息进入事件队列,请使用 fastevent 包。

    Joysticks(游戏手柄)只有在设备初始化后才会发送事件。

    一个 EventType 事件对象包含一个事件类型标识符和一组成员数据(事件对象不包含方法,只有数据)。EventType 对象从 Python 的事件队列中获得,你也可以使用 pygame.event.Event() 函数创建自定义的新事件。

    由于 SDL 的事件队列限制了事件数量的上限(标准的 SDL 1.2 限制为 128),所以当队列已满时,新的事件将会被扔掉。为了防止丢失事件消息,尤其是代表退出的输入事件(因为当用户点击退出按钮没有反应,往往会被认为“死机”了),你的程序必须定期检测事件,并对其进行处理。

    为了加快事件队列的处理速度,可以使用 pygame.event.set_blocked() 函数阻止一些我们不关注的事件进入队列中。

    所有的 EventType 实例对象都拥有一个事件类型标识符,属性名是 type。你也可以通过事件对象的 __dict__ 属性来完全访问其他属性。所有其他成员属性的值都是通过事件对象的字典来传递。

    在做调试和实验时,你可以打印事件对象以及相应的类型和成员。来自系统的事件都有一个事件类型和对应的成员属性,下边是每个事件类型以及对应的成员属性列表:

    事件类型

    成员属性

    QUITnone
    ACTIVEEVENTgain, state
    KEYDOWNunicode, key, mod
    KEYUPkey, mod
    MOUSEMOTIONpos, rel, buttons
    MOUSEBUTTONUPpos, button
    MOUSEBUTTONDOWNpos, button
    JOYAXISMOTIONjoy, axis, value
    JOYBALLMOTIONjoy, ball, rel
    JOYHATMOTIONjoy, hat, value
    JOYBUTTONUPjoy, button
    JOYBUTTONDOWNjoy, button
    VIDEORESIZEsize, w, h
    VIDEOEXPOSEnone
    USEREVENTcode

    事件支持等值比较。如果两个事件具有相同的类型和属性值,那么认为两个事件是相等的。(Pygame 1.9.2 新增加的)

    函数详解

    pygame.event.pump()

    让 Pygame 内部自动处理事件。

    pump() -> None

    对于游戏中的每一帧,你都需要通过某种形式去调用事件队列,这将确保你的程序在内部可以与操作系统的其他部分进行交互。如果你不打算使用其他事件函数,那么你应该调用 pygame.event.pump(),这将允许 Pygame 内部自动处理事件。

    如果你的程序始终通过其他 event 模块的函数处理队列中的事件,那么该函数是没必要的。

    事件队列中的内部处理是非常重要的事情。主窗口可能需要重新绘制或对系统做出响应。如果你太长时间没有调用事件队列,系统可能会认定你的程序已锁定(假死)。

    pygame.event.get()

    从队列中获取事件。

    get() -> Eventlist

    get(type) -> Eventlist

    get(typelist) -> Eventlist

    这将获取并从队列中删除事件。如果指定一个或多个 type 参数,那么只获取并删除指定类型的事件。

    请注意,如果你只从队列中获取和删除指定的事件,那么久而久之,队列可能被你不关注的事件所填满。

    pygame.event.poll()

    从队列中获取一个事件。

    poll() -> EventType instance

    从队列中返回并删除一个事件。

    如果事件队列为空,那么会立刻返回类型为 pygame.NOEVENT 的事件。

    pygame.event.wait()

    等待并从队列中获取一个事件。

    wait() -> EventType instance

    从队列中返回并删除一个事件。如果队列为空,那么该函数将持续等待直至队列中有一个事件。当程序在等待时,它将保持睡眠状态。这对于希望与其他应用程序共享系统来说,是非常重要的。

    pygame.event.peek()

    检测某类型事件是否在队列中。

    peek(type) -> bool

    peek(typelist) -> bool

    如果参数指定的类型的事件存在于队列中,返回 True。

    如果参数指定多个类型的事件,则只需队列中拥有其中的任何一个事件便返回 True。

    pygame.event.clear()

    从队列中删除所有的事件。

    clear() -> None

    clear(type) -> None

    clear(typelist) -> None

    从队列中删除所有的事件,如果通过参数指定事件的类型,则删除该类型的所有事件。该函数的效果跟 pygame.event.get() 相同,只是没有返回任何东西。当处理完关注的事件后,清空整个队列可以提高一些效率。

    pygame.event.event_name()

    通过 id 获得该事件的字符串名字。

    event_name(type) -> string

    Pygame 通过整数 id 代表事件类型。如果你需要将这些类型的事件展示给用户看,那么你需要将它们转换成字符串(一堆数字谁知道你想表示啥?)。该函数将返回事件类型对应的字符串名字。返回值是以单词大写的样式(小甲鱼温馨提示:DanCiDaXieDe)。

    pygame.event.set_blocked()

    控制哪些事件禁止进入队列。

    set_blocked(type) -> None

    set_blocked(typelist) -> None

    set_blocked(None) -> None

    参数指定的类型的事件均不允许出现在事件队列中。默认是允许所有事件进入队列。多次禁止同一类型的事件并不会引发什么问题。

    如果传入 None,则表示允许所有的事件进入队列。

    pygame.event.set_allowed()

    控制哪些事件允许进入队列。

    set_allowed(type) -> None

    set_allowed(typelist) -> None

    set_allowed(None) -> None

    参数指定的类型的事件均允许出现在事件队列中。默认是允许所有事件进入队列。多次允许同一类型的事件并不会引发什么问题。

    如果传入 None,则表示禁止所有的事件进入队列。

    pygame.event.get_blocked()

    检测某一类型的事件是否被禁止进入队列。

    get_blocked(type) -> bool

    如果参数指定类型的事件被禁止进入队列,则返回 True。

    pygame.event.set_grab()

    控制输入设备与其他应用程序的共享。

    set_grab(bool) -> None

    当你的程序运行在窗口环境中,它将与其他拥有焦点的应用程序分享鼠标和键盘设备的输入。如果你的程序设置事件独占为 True,那么你的程序将锁定所有的输入(小甲鱼温馨提示:不共享给其他程序了)。

    最好不要经常独占输入,因为这将阻止用户在操作系统上的其他操作。

    pygame.event.get_grab()

    检测程序是否共享输入设备。

    get_grab() -> bool

    当程序独占输入事件时,返回 True。使用 pygame.event.set_grab() 函数控制这一状态。

    pygame.event.post()

    放置一个新的事件到队列中。

    post(Event) -> None

    该函数将放置一个新的事件到事件队列的末端。这些事件将最迟被其他队列函数获取。

    该函数通常用于放置 pygame.USEREVENT(用户自定义事件)事件到队列中。尽管你可以放置所有类型的事件,但你需要确保为系统事件类型相应的属性传递合适的值。

    如果 SDL 事件队列已满,将抛出 pygame.error 异常。

    pygame.event.Event()

    创建一个新的事件对象。

    Event(type, dict) -> EventType instance

    Event(type, **attributes) -> EventType instance

    根据参数给定的类型创建一个新的事件。dict 参数指定事件的属性以及相应的值。

    class pygame.event.EventType

    代表 SDL 事件的 Pygame 对象。

    pygame.event.EventType.type  —  SDL event type identifier.

    pygame.event.EventType.__dict__  —  vent object attribute dictionary

    用于代表 SDL 事件的 Pygame 对象。通过 pygame.event.Event() 创建用户自定义事件。EventType 类型并不是直接可以被调用的。EventType 实例对象支持属性赋值和删除。

    type

    SDL 事件类型标识符。

    type -> int

    只读。预定义事件标识符是 QUIT 和 MOUSEMOTION 等。对于用于创建的事件对象,这是传递给 pygame.event.Event() 的 type 参数。

    __dict__

    事件对象的属性字典。

    __dict__ -> dict

    只读。事件类型指定的属性。例如,KEYDOWN 事件包含 unicode,key 和 mod 属性。

    可变属性是 Pygame 1.9.2 新增加的。

    来源:https://blog.csdn.net/qq_41556318/article/details/86303039

    展开全文
  • esp-idf 之事件循环(Event Loop)例程详解

    千次阅读 2020-06-20 19:03:45
    本文是将Default Event Loop:esp-idf/examples/system/esp_event/default_event_loop at release/v3.3 · espressif/esp-idf 例程内的README和代码注释翻译一下,便于各位看官理解并理顺思路。 README 事件循环库...

    本文是将Default Event Loop:esp-idf/examples/system/esp_event/default_event_loop at release/v3.3 · espressif/esp-idf 例程内的README和代码注释翻译一下,便于各位看官理解并理顺思路。

    README

    事件循环库Event Loop Library (‘esp_event’) 默认事件循环例程Default Event Loop Example

    本例程是事件循环库的一个示例。为了保持简单,示例仅限于使用默认事件循环。
    默认事件循环是系统自带的事件循环,在一般情况下已经够用。
    如果需要,用户也可以参考 user_event_loops 例程创建用户自定义的事件循环。

    例程的内容如下:

    事件的声明与定义 (Declaring and Defining Events)

    本例程展示了如何在头文件中声明event base和event ID,并在源文件中进行定义。
    在头文件中使用了 ESP_EVENT_DECLARE_BASE这个宏来声明 event base, 而event IDs 在一个枚举enum中进行声明(参考esp-idf/event_source.h at release/v3.3 · espressif/esp-idf)。
    。在源文件 main.c 中使用了 ESP_EVENT_DEFINE_BASE这个宏来定义event base.

    创建默认事件循环 (Creating the Default Event Loop)

    本例程中使用了esp_event_loop_create_default这个API来创建默认事件循环。

    向默认事件循环发送事件 (Posting Events to the Default Event Loop)

    简单说,就是向默认事件循环发送事件相当于事件的handler依次执行队列中的命令。 使用API esp_event_post来向默认事件循环发送事件。例程中也展示了如何同时传递事件数据。

    Handler的注册与注销 (Handler Registration/Unregistration)

    本例程使用 esp_event_handler_register注册了三个handler:
    (1) 特定事件
    (2) 特定event base的任意事件
    (3) 任意事件
    使用 esp_event_handler_unregister来注销handler。注销handler之后,即便事件此前已注册的事件再次被发送时,也不会再执行了。

    例程解析 (Example Flow Explained)

    以例程的LOG输出来解释:

    I (276) default_event_loop: setting up
    I (276) default_event_loop: starting event sources
    I (276) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: posting to default loop
    I (276) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 1 out of 5
    I (296) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: timer_started_handler
    I (306) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: timer_any_handler
    I (316) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: all_event_handler
    I (326) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: task_iteration_handler, executed 1 times
    I (336) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler
    I (806) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 2 out of 5
    I (806) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: task_iteration_handler, executed 2 times
    I (806) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler
    I (1276) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: posting to default loop
    I (1276) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_expiry_handler, executed 1 out of 3 times
    I (1286) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_any_handler
    I (1296) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: all_event_handler
    I (1306) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 3 out of 5
    I (1316) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: unregistering task_iteration_handler
    I (1316) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: task_iteration_handler, executed 3 times
    I (1336) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler
    I (1846) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 4 out of 5
    I (1846) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler
    I (2276) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: posting to default loop
    I (2276) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_expiry_handler, executed 2 out of 3 times
    I (2286) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_any_handler
    I (2296) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: all_event_handler
    I (2346) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 5 out of 5
    I (2346) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler
    I (3276) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: posting to default loop
    I (3276) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: posting to default loop
    I (3286) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_expiry_handler, executed 3 out of 3 times
    I (3296) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_any_handler
    I (3306) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: all_event_handler
    I (3316) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: timer_stopped_handler
    I (3326) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: deleted timer event source
    I (3326) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: timer_any_handler
    I (3336) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: all_event_handler
    I (3346) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: deleting task event source
    
    

    设置 (Setting)

    本例程使用了两个事件源:一个循环定时器和一个包含循环的任务。定时器在如下情况会产生事件:

    1. 定时器启动
    2. 定时器间隔时间到
    3. 定时器停止
      当任务每次循环时,也会产生事件。

    除了如上事件对应的handler之外,还有一个handler,在任意事件发生的时候都会执行。
    例程设定了定时器的重复执行次数和任务迭代次数。当定时器循环指定次数的时候,定时器会被停止。当任务迭代达到指定次数时,任务会被删除。对于任务循环来说,还有另外一个设定:即当迭代达到某个次数的时候,对应的handler被注销。

    分步解析 (Step-by-Step Explanation)

    如下输出内容即为关键点:
    a.

    I (297)  default_event_loop: setting up
    

    此时默认事件循环已经被创建,同时各个事件handler已经被注册。

    b.

    I (276) default_event_loop: starting event sources
    I (276) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: posting to default loop
    I (276) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 1 out of 5
    

    两个事件源已经启动,并向默认事件循环发送事件。

    c.

    I (296) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: timer_started_handler
    I (306) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: timer_any_handler
    I (316) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: all_event_handler
    
    I (326) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: task_iteration_handler, executed 1 times
    I (336) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler
    

    (b) 中发送的事件对应handler已被执行,另外
    timer_started_handlertask_iteration_handler, timer_any_handlerall_event_handler 都被执行。

    任意定时器事件均会触发timer_any_handler的执行。可以看到定时器间隔时间到和定时器停止的时候也执行了timer_any_handler

    任意事件均会触发all_event_handler的执行。所以在 TIMER_EVENTS:TIMER_EVENT_STARTEDTASK_EVENTS:TASK_ITERATION_EVENT 两个事件发生的时候可以看到它在执行。

    对于定时器和任务事件,esp_event确保了他们是按照handler注册的顺序执行的。
    如下输出也是如此,事件的发送和handler的执行都完全依照上述注册的顺序。

    d.

    ...
    I (1316) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: unregistering task_iteration_handler
    

    此时 task_iteration_handler 已注销, 因此当 TASK_EVENTS:TASK_ITERATION_EVENT发送时已不再执行。

    I (1867) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 4 out of 5
    I (1867) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler
    
    ...
    
    I (1846) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 4 out of 5
    I (1846) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handle
    

    任务迭代事件继续发送,但是只有 all_event_handler 被执行。

    e.

    ...
    I (3276) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: posting to default loop
    I (3276) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: posting to default loop
    I (3286) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_expiry_handler, executed 3 out of 3 times
    I (3296) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_any_handler
    I (3306) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: all_event_handler
    I (3316) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: timer_stopped_handler
    I (3326) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: deleted timer event source
    

    When the periodic timer expiry limit is reached, the event TIMER_EVENTS:TIMER_EVENT_STOPPED is posted to the loop. The periodic timer is consequently deleted in the handler timer_stopped_handler.
    当定时器循环达到指定次数的时候,TIMER_EVENTS:TIMER_EVENT_STOPPED被发送到事件循环,然后在timer_stopped_handler中定时器被删除。

    ...
    I (3346) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: deleting task event source
    ...
    

    此时发送迭代事件的任务也被删除。例程执行结束。

    代码:

    /* esp_event (event loop library) basic example
       This example code is in the Public Domain (or CC0 licensed, at your option.)
       Unless required by applicable law or agreed to in writing, this
       software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
       CONDITIONS OF ANY KIND, either express or implied.
    */
    
    #include "esp_log.h"
    
    #include "freertos/FreeRTOS.h"
    #include "freertos/task.h"
    
    #include "event_source.h"
    
    static const char* TAG = "default_event_loop";
    
    static char* get_id_string(esp_event_base_t base, int32_t id) {
        char* event = "";
        if (base == TIMER_EVENTS) {
            switch(id) {
                case TIMER_EVENT_STARTED:
                event = "TIMER_EVENT_STARTED";
                break;
                case TIMER_EVENT_EXPIRY:
                event = "TIMER_EVENT_EXPIRY";
                break;
                case TIMER_EVENT_STOPPED:
                event = "TIMER_EVENT_STOPPED";
                break;
            }
        } else {
            event = "TASK_ITERATION_EVENT";
        }
        return event;
    }
    
    /* 循环定时器相关的event base定义 */
    ESP_EVENT_DEFINE_BASE(TIMER_EVENTS);
    
    esp_timer_handle_t TIMER;
    
    
    //定时器回调,回调中向默认事件循环发送事件
    static void timer_callback(void* arg)
    {
        ESP_LOGI(TAG, "%s:%s: posting to default loop", TIMER_EVENTS, get_id_string(TIMER_EVENTS, TIMER_EVENT_EXPIRY));
        ESP_ERROR_CHECK(esp_event_post(TIMER_EVENTS, TIMER_EVENT_EXPIRY, NULL, 0, portMAX_DELAY));
    }
    
    // 定时器启动事件的Handler 
    static void timer_started_handler(void* handler_args, esp_event_base_t base, int32_t id, void* event_data)
    {
        ESP_LOGI(TAG, "%s:%s: timer_started_handler", base, get_id_string(base, id));
    }
    
    
    //定时器循环事件handler,每次发送定时到达事件,同时此回调记录定时器执行次数,达到指定次数的时候会停止定时器并发送定时器停止事件。
    static void timer_expiry_handler(void* handler_args, esp_event_base_t base, int32_t id, void* event_data)
    {
        static int count = 0;
    
        count++;
    
        if (count >= TIMER_EXPIRIES_COUNT) {
            // 停止定时器
            ESP_ERROR_CHECK(esp_timer_stop(TIMER));
    
            ESP_LOGI(TAG, "%s:%s: posting to default loop", base, get_id_string(base, TIMER_EVENT_STOPPED));
    
            // 发送定时器停止事件
            ESP_ERROR_CHECK(esp_event_post(TIMER_EVENTS, TIMER_EVENT_STOPPED, NULL, 0, portMAX_DELAY));
        }
    
        ESP_LOGI(TAG, "%s:%s: timer_expiry_handler, executed %d out of %d times", base, get_id_string(base, id), count, TIMER_EXPIRIES_COUNT);
    }
    
    
    //任意定时器事件handler,在定时器开启、时间到、停止时均会执行
    static void timer_any_handler(void* handler_args, esp_event_base_t base, int32_t id, void* event_data)
    {
        ESP_LOGI(TAG, "%s:%s: timer_any_handler", base, get_id_string(base, id));
    }
    
    
    //定时器停止事件handler。定时器停止之后即可安全删除定时器。
    static void timer_stopped_handler(void* handler_args, esp_event_base_t base, int32_t id, void* event_data)
    {
        ESP_LOGI(TAG, "%s:%s: timer_stopped_handler", base, get_id_string(base, id));
    
        // 删除定时器
        esp_timer_delete(TIMER);
    
        ESP_LOGI(TAG, "%s:%s: deleted timer event source", base, get_id_string(base, id));
    }
    
    /* 任务相关的event base定义 */
    ESP_EVENT_DEFINE_BASE(TASK_EVENTS)
    
    static void task_iteration_handler(void* handler_args, esp_event_base_t base, int32_t id, void* event_data)
    {
        int iteration = *((int*) event_data);
        ESP_LOGI(TAG, "%s:%s: task_iteration_handler, executed %d times", base, get_id_string(base, id), iteration);
    }
    
    static void task_event_source(void* args)
    {
        for(int iteration = 1; iteration <= TASK_ITERATIONS_COUNT; iteration++) {
    
            ESP_LOGI(TAG, "%s:%s: posting to default loop, %d out of %d", TASK_EVENTS,
                    get_id_string(TASK_EVENTS, TASK_ITERATION_EVENT), iteration, TASK_ITERATIONS_COUNT);
    
    
         //发送任务迭代事件,迭代次数同时被传递给handler。请注意传递的数据是原数据的深拷贝。
            ESP_ERROR_CHECK(esp_event_post(TASK_EVENTS, TASK_ITERATION_EVENT, &iteration, sizeof(iteration), portMAX_DELAY));
    
            if (iteration == TASK_ITERATIONS_UNREGISTER){
                ESP_LOGI(TAG, "%s:%s: unregistering task_iteration_handler", TASK_EVENTS, get_id_string(TASK_EVENTS, TASK_ITERATION_EVENT));
                ESP_ERROR_CHECK(esp_event_handler_unregister(TASK_EVENTS, TASK_ITERATION_EVENT, task_iteration_handler));
            }
    
            vTaskDelay(pdMS_TO_TICKS(TASK_PERIOD));
        }
    
        vTaskDelay(pdMS_TO_TICKS(TASK_PERIOD));
    
        ESP_LOGI(TAG, "%s:%s: deleting task event source", TASK_EVENTS, get_id_string(TASK_EVENTS, TASK_ITERATION_EVENT));
    
        vTaskDelete(NULL);
    }
    
    /* 所有时间的handler*/
    static void all_event_handler(void* handler_args, esp_event_base_t base, int32_t id, void* event_data)
    {
        ESP_LOGI(TAG, "%s:%s: all_event_handler", base, get_id_string(base, id));
    }
    
    /* Example main */
    void app_main(void)
    {
        ESP_LOGI(TAG, "setting up");
    
        // Create the default event loop
        ESP_ERROR_CHECK(esp_event_loop_create_default());
    
        // 注册特定定时器事件handler
        ESP_ERROR_CHECK(esp_event_handler_register(TIMER_EVENTS, TIMER_EVENT_STARTED, timer_started_handler, NULL));
        ESP_ERROR_CHECK(esp_event_handler_register(TIMER_EVENTS, TIMER_EVENT_EXPIRY, timer_expiry_handler, NULL));
        ESP_ERROR_CHECK(esp_event_handler_register(TIMER_EVENTS, TIMER_EVENT_STOPPED, timer_stopped_handler, NULL));
    
        //注册所有定时器事件的handler,包括定时器开启、时间到和停止事件
        ESP_ERROR_CHECK(esp_event_handler_register(TIMER_EVENTS, ESP_EVENT_ANY_ID, timer_any_handler, NULL));
    
        // 注册迭代任务handler
        ESP_ERROR_CHECK(esp_event_handler_register(TASK_EVENTS, TASK_ITERATION_EVENT, task_iteration_handler, NULL));
    
        
    //注册所有事件的handler,定时器事件和任务迭代事件都会触发它的执行
    ESP_ERROR_CHECK(esp_event_handler_register(ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, all_event_handler, NULL));
    
        // 创建并启动定时器事件源
        esp_timer_create_args_t timer_args = {
            .callback = &timer_callback,
        };
    
        ESP_ERROR_CHECK(esp_timer_create(&timer_args, &TIMER));
    
        ESP_LOGI(TAG, "starting event sources");
    
         // 创建任务事件源
        xTaskCreate(task_event_source, "task_event_source", 2048, NULL, uxTaskPriorityGet(NULL), NULL);
    
        ESP_ERROR_CHECK(esp_timer_start_periodic(TIMER, TIMER_PERIOD));
    
        // 发送定时器启动事件
        ESP_LOGI(TAG, "%s:%s: posting to default loop", TIMER_EVENTS, get_id_string(TIMER_EVENTS, TIMER_EVENT_STARTED));
        ESP_ERROR_CHECK(esp_event_post(TIMER_EVENTS, TIMER_EVENT_STARTED, NULL, 0, portMAX_DELAY));
    }
    
    展开全文
  • Kubernetes:Event-事件处理机制

    千次阅读 2020-03-13 22:30:55
    Event前言 当集群中的 node 或 pod 异常时,大部分用户会使用 kubectl 查看对应的 events,那么 events 是从何而来? 其实 K8s 中的各个组件会将运行时产生的各种事件汇报到 apiserver,对于 K8s 中的可描述资源,...
  • keybd_event 使用方法

    万次阅读 多人点赞 2019-09-28 19:32:24
    Windows 提供了一个模拟键盘 API 函数 Keybd_event(),使用该函数可以相应的屏蔽键盘的动作。Keybd_event()函数能触发一个按键事件,也就是说会产生一个 WM_KEYDOWN 或 WM_KEYUP 消息。 该函数原型如下: ...
  • PostgreSQL中的等待事件wait_event

    千次阅读 2020-07-12 18:47:48
    MQ_SEND, WAIT_EVENT_PARALLEL_BITMAP_SCAN, WAIT_EVENT_PARALLEL_CREATE_INDEX_SCAN, WAIT_EVENT_PARALLEL_FINISH, WAIT_EVENT_PROCARRAY_GROUP_UPDATE, WAIT_EVENT_PROMOTE, WAIT_EVENT_REPLICATION_ORIGIN_...
  • } } 4.3 创建监听者 @Log4j2 @Component public class AEventListener { @EventListener public void listener(TestEvent event) { log.info("监听到数据1:{}", event.getMessage()); } } 调用接口 @...
  • 使用 libevent 函数之前需要分配一个或者多个 event_base 结构体。每个 event_base 结构体持有一个事件集合,可以检测以确定哪个事件是激活的。 4.1.1 创建默认的event_base struct event_base *event_base_new...
  • Spring Event事件通知机制

    万次阅读 多人点赞 2019-03-11 21:10:57
    protected void publishEvent(Object event, @Nullable ResolvableType eventType) { Assert.notNull(event, "Event must not be null"); // Decorate event as an ApplicationEvent if necessary ...
  • InputDispatcher: Asynchronous input event injection succeeded. 全局搜索找到 frameworks\native\services\inputflinger\InputDispatcher.cpp 中 这就有点难顶了,cpp 中想要通知 java 层还是有点困难的
  • UVM : uvm_event, uvm_event_pool

    千次阅读 多人点赞 2019-03-24 12:09:45
    event, semaphore和mailbox 。 而在UVM中event进化成 uvm_event ,不仅仅拥有达成不同组件进程之间同步的功能,还能像TLM通信一样传递数据,并且作用范围更广(TLM通信只能在uvm_component之间,而uvm_event不限于...
  • C# Event/UnityEvent辨析

    万次阅读 多人点赞 2017-10-27 16:21:24
    Event作为C#语言特性的一部分,在.Net开发中具有比较重要的作用。当我们使用C#作为脚本语言编写Unity游戏时,也经常会需要使用Event解决各种问题。然而,相比于传统C#语言的Event,UnityEvent基于Unity引擎做了一些...
  • @EventListener注解使用及源码解析

    万次阅读 多人点赞 2019-07-29 15:54:20
    一、简介 @EventListener是一种事件驱动编程在spring4.2的时候开始有的,早期可以实现ApplicationListener接口, 想了解下ApplicationListener的可以参考下这篇文章...内部实现原...
  • Spring 执行顺序:Event 事件

    千次阅读 2019-08-29 21:14:23
    代码:https://gitee.com/free/boot-order/tree/master/src/main/java/com/github/abel533/event 实现 ApplicationListener 接口,输出所有事件。 当以 @Component 方式配置时 事件触发顺序如下: Application...
  • keybd_event模拟键盘输入

    万次阅读 多人点赞 2018-08-23 22:30:32
    Windows提供了一个模拟键盘API函数keybd_event(),该函数原型为:keybd_event(bVk, bScan, dwFlags, dwExtraInfo),其中: 第一个参数:虚拟键码(键盘键码对照表见附录); 第二个参数:硬件扫描码,一般设置为0...
  • Pygame详解(四):event 模块

    万次阅读 多人点赞 2019-01-11 15:38:36
    pygame.event 用于处理事件与事件队列的 Pygame 模块。 函数 pygame.event.pump() — 让 Pygame 内部自动处理事件 pygame.event.get() — 从队列中获取事件 pygame.event.poll() — 从队列中获取一个事件...
  • 详解 QT Event 以及 Event Filter 事件处理

    万次阅读 多人点赞 2018-08-09 10:37:23
    QT Event以及EventFilter事件处理是本文要介绍的内容,详细内容如下,先来看内容。EventEvent Filters: 1、手动发送事件流程: (1)构造自己的事件对象: QEvent*evt=newQEvent(QEvent::Close); (2)...
  • Spring publishevent事件处理

    千次阅读 2021-01-17 23:16:42
    这个一般什么时候使用,我们一般是在不同的bean直接进行信息传递,比如我们beanA的事件处理完后,需要beanB进行处理一些业务逻辑的时候这种情况就一般可以使用publish-event解决 原理 其实事件模型我们并不陌
  • unity 监测UI EventTrigger事件

    千次阅读 2022-03-22 17:59:33
    EventTrigger的所有事件类型 PointerEnter = 0 鼠标进入 PointerExit = 1 鼠标离开 PointerDown = 2 鼠标按下 PointerUp = 3 鼠标抬起 PointerClick = 4 鼠标点击(鼠标抬起时已不在原UI上时不会触发,在PointerUp...
  • libevent源码解析(二)event接口函数

    千次阅读 2018-06-23 19:21:58
    一.前言   在上一篇中,我们提到了event... * event_new(), event_free(), event_assign(), event_get_assignment(), * event_add(), event_del(), event_active(), event_pending(), * event_get_fd(......
  • function(event)中的event详解

    千次阅读 2021-01-06 15:26:57
    一、function(event)中的event是什么? event对象是个形式参数,代表事件的状态;比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。 关于event对象 在触发的事件的函数里面我们会接收到一个...
  • Linux perf 1.1、perf_event内核框架

    万次阅读 多人点赞 2018-07-25 12:18:53
    perf_event还需要做cpu匹配,符合(event->cpu == -1 || event->cpu == smp_processor_id())条件的event才能链接到pmu上。 9、 enable_on_exec : perf_event的状态(event->state)典型值有以下3种: ...
  • Spring源码-事件监听机制(@EventListener实现方式)

    万次阅读 多人点赞 2019-11-06 18:33:29
    在看@EventListener之前需要先知道 继承EventListener方式在底层是怎么实现了,可以参见前一篇博客Spring源码-事件监听机制(实现EventListener接口)。 先梳理一下,首先Ioc容器启动的时候,ApplicationContext的...
  • event_base

    千次阅读 2018-08-10 19:57:32
    event_base 介绍   一个event_base就是一个Reactor框架。我们在调用任何Libevent的函数前,我们都是需要先申请 event_base 结构体。对于一个event_base结构来说,它会保存一系列的event事件并且以轮训的方式去...
  • pygame中event模块方法详解

    千次阅读 2020-05-20 14:04:27
    pygame.event.pump() pygame.event.get() pygame.event.poll() pygame.event.wait() pygame.event.peek() pygame.event.clear() pygame.event.event_name() pygame.event.set_blocked() pygame.event.set_...
  • 传统蓝牙EVENT(部分) 序号 EVENT 描述 0x01 Inquiry Complete Event 搜索完成 0x02 Inquiry Result Event 搜索结果 0x03 Connection Complete Event 连接完成 0x04 Connection Request Event 连接请求 0x05 ...
  • springboot publish event 事件机制demo

    千次阅读 2020-11-30 16:58:48
    springboot publish event 事件机制demo 复制下面全部代码,右键包名,粘贴即可生成java类,执行即可看到效果。 事件机制: 需要自定义一个事件类继承ApplicationEvent; 需要自定义一个监听器类实现Application...
  • js中事件对象event

    万次阅读 多人点赞 2018-03-06 16:40:10
    一、Event对象 Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。 事件通常与函数结合使用,函数不会在事件发生前被执行! 当一个事件发生的时候,和当前这个...
  • LVGL lv_event事件(10)

    千次阅读 2021-01-02 16:30:37
    lv_events ... LV_EVENT_PRESSED, /**< The object has been pressed*/ LV_EVENT_PRESSING, /**< The object is being pressed (called continuously while pressing)*/ LV_EVENT_PRESS_LOST

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,792,723
精华内容 717,089
关键字:

event

友情链接: Min.zip