事件介绍

事件的处理机制非常的复杂,属于PyQt底层的事,不必我们关心,学会使用就行。如果说事件是用来创建窗口,那么信号与槽就是用来对这个控件进行处理。事件属于低级的处理方式,信号与槽是高级的处理方式,一般信号与槽处理不了的问题,再使用事件处理。信号与槽功能强大使用简单但是不能解决所有的问题,事件使用麻烦但是可以处理全部的问题。事件的处理主要是重载类方法,信号与槽的处理主要是绑定、发送以及处理。

事件

  1. 重写mousePressEvent,keyPressEvent,paintEvent等方法,最常用(控件级)

  2. 重写QObject.event方法,一般在PyQt没有提供该事件的处理方法时使用(控件级)

  3. 安装事件过滤器:如果对QObject调用installEventFilter,相当于对这个QObject对象添加了一个过滤器。对于QObject的全部事件来说,都会先经过过滤器的处理,在过滤器里面就可以进行我们自己的处理,比如修改丢弃等,慎用,因为会处理所有的事件,会降低效率(控件级)

  4. 在QApplication中安装事件过滤器:比QObject的过滤器更强大,对所有的QObject的所有事件进行过滤,且第一时间捕获。事件的过滤先经过QApplication的处理再进过QObject的处理,必须慎用(应用级)

  5. 重写QApplication的notify方法,要想在任何事件被处理之前捕获事件,唯一的方法就是重写QApplication的notify方法,一般只在调试中使用(应用级)

 事件处理流程(紫色部分是应用级处理,绿色部分是对象级处理)

例子

import sys

from PyQt5.QtCore import QEvent
from PyQt5.QtWidgets import QApplication, QWidget class MyWidget(QWidget):
def __init__(self):
super(MyWidget, self).__init__() def mousePressEvent(self, mouseEvent):
print('MyWidget.mousePressEvent')
return QWidget.mousePressEvent(self, mouseEvent) def event(self, event):
if event.type() == QEvent.MouseButtonPress:
print('MyWidget.event')
return QWidget.event(self, event) def eventFilter(self, object, event):
if event.type() == QEvent.MouseButtonPress:
print('MyWidget.eventFilter')
return QWidget.eventFilter(self, object, event) class MyQApplication(QApplication):
def __init__(self, param):
super(MyQApplication, self).__init__(param) def notify(self, object, event):
if event.type() == QEvent.MouseButtonPress:
print('MyQApplication.notify')
return QApplication.notify(self, object, event) def eventFilter(self, object, event):
if event.type() == QEvent.MouseButtonPress:
print('MyQApplication.eventFilter')
return QApplication.eventFilter(self, object, event) if __name__ == '__main__':
app = MyQApplication(sys.argv)
app.installEventFilter(app)
w = MyWidget()
w.installEventFilter(w)
w.resize(500, 300)
w.move(300, 300)
w.setWindowTitle('Simple')
w.show()
sys.exit(app.exec_())

信号与槽

信号与槽是PyQt的核心机制,也是对象与对象之间的通信方法。信号与槽函数的对应方式是多对多,且信号可以连接信号。除了控件默认的信号外,可以自己定义和实现信号。

信号定义:

mySignal = pyqtSignal([param])

连接信号到槽:

mySignal.connect(handlerFunc)

发送信号:

mySignal.emit([param])

断开信号与槽:

mySignal.disconnect(handlerFunc)

例子:自定义信号并实现与槽的链接

import sys
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton class MyWidget(QWidget):
mySignal = pyqtSignal() def __init__(self):
super(MyWidget, self).__init__()
button = QPushButton(self)
button.setText('点我')
button.clicked.connect(self.buttonClicked)
self.mySignal.connect(self.mySignalHandler) def buttonClicked(self):
print('button clicked emit and handler')
self.mySignal.emit() def mySignalHandler(self):
print('my signal emit and handler') if __name__ == '__main__':
app = QApplication(sys.argv)
w = MyWidget()
w.resize(500, 300)
w.move(300, 300)
w.setWindowTitle('Simple')
w.show()
sys.exit(app.exec_())

信号与槽高级玩法

信号重载

import sys
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton class MyWidget(QWidget):
# 无参数信号
mySignal_no_aram = pyqtSignal()
# 带一个整型参数信号
mySignal_int = pyqtSignal(int)
# 带一个整型或字符串信号
mySignal_int_or_str = pyqtSignal([int], [str])
# 带两个参数,int和srt 或 str和str
mySignal_two_param = pyqtSignal([int, str], [str, str]) def mySignal_no_aram_handler(self):
print('mySignal_no_aram_handler') def mySignal_int_handler(self):
print('mySignal_int_handler') def mySignal_int_or_str_int_handler(self):
print('mySignal_int_or_str_int_handler') def mySignal_int_or_str_str_handler(self):
print('mySignal_int_or_str_str_handler') def mySignal_two_param_int_str_handler(self):
print('mySignal_two_param_int_str_handler') def mySignal_two_param_str_str_handler(self):
print('mySignal_two_param_str_str_handler') def __init__(self):
super(MyWidget, self).__init__()
button = QPushButton(self)
button.setText('点我')
button.clicked.connect(self.onClicked) # 绑定信号到槽函数
self.mySignal_no_aram.connect(self.mySignal_no_aram_handler)
self.mySignal_int.connect(self.mySignal_int_handler)
self.mySignal_int_or_str[int].connect(self.mySignal_int_or_str_int_handler)
self.mySignal_int_or_str[str].connect(self.mySignal_int_or_str_str_handler)
self.mySignal_two_param[int, str].connect(self.mySignal_two_param_int_str_handler)
self.mySignal_two_param[str, str].connect(self.mySignal_two_param_str_str_handler) def onClicked(self):
# 发送信号
self.mySignal_no_aram.emit()
self.mySignal_int.emit(1)
self.mySignal_int_or_str[int].emit(2)
self.mySignal_int_or_str[str].emit('abc')
self.mySignal_two_param[int, str].emit(3, 'def')
self.mySignal_two_param[str, str].emit('abc', 'def') if __name__ == '__main__':
app = QApplication(sys.argv)
w = MyWidget()
w.resize(500, 300)
w.move(300, 300)
w.setWindowTitle('Simple')
w.show()
sys.exit(app.exec_())

使用自定义参数

import sys
from functools import partial
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton class MyWidget(QWidget):
def __init__(self):
super(MyWidget, self).__init__()
button1 = QPushButton(self)
button1.setText('button1')
button1.move(10, 10)
button2 = QPushButton(self)
button2.setText('button2')
button2.move(10, 50) # button1.clicked.connect(lambda: self.onClicked(button1))
# button2.clicked.connect(lambda: self.onClicked(button2))
# 等价
button1.clicked.connect(partial(self.onClicked, button1))
button2.clicked.connect(partial(self.onClicked, button2)) def onClicked(self, btn):
print("%s" % btn.text()) if __name__ == '__main__':
app = QApplication(sys.argv)
w = MyWidget()
w.resize(500, 300)
w.move(300, 300)
w.setWindowTitle('Simple')
w.show()
sys.exit(app.exec_())

使用装饰器定义信号与槽

import sys
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton class MyWidget(QWidget):
def __init__(self):
super(MyWidget, self).__init__()
button = QPushButton(self)
button.setText('点击') # 设置发送者名称
button.setObjectName('button')
# 实现绑定
QtCore.QMetaObject.connectSlotsByName(self) # 槽函数命名规则:on_发送者名称_发射信号名称(self, param)
@QtCore.pyqtSlot()
def on_button_clicked(self):
print('you clicked button') if __name__ == '__main__':
app = QApplication(sys.argv)
w = MyWidget()
w.resize(500, 300)
w.move(300, 300)
w.setWindowTitle('Simple')
w.show()
sys.exit(app.exec_())

PyQt5事件处理的更多相关文章

  1. Ubuntu 14.04下搭建Python3.4 + PyQt5.3.2 + Eric6.0开发平台

    引言 找了很多Python GUI工具集,还是觉得PyQt比较理想,功能强大跨平台,还支持界面设计器.花一天时间折腾了Ubuntu14.04(32位)+ Python3.4 + Qt5.3.2 + P ...

  2. PyQt5多点触控写字板实现及困惑

    Qt支持程序多点触控,就想使用PyQt5做一个触控画板,经过几番周折,查阅了TouchEvent官方文档,又参考了一篇QT for Android的例子,采用eventfilter过滤器来识别触屏事件 ...

  3. pyqt5之简单窗口的创建

    在学完tkinter后,发现tkinter在布局方面特别的不方便(Tkinter资料:http://effbot.org/tkinterbook/tkinter-index.htm),因此学习pyqt ...

  4. PyQt5基础应用一

    一.PyQt5基础   1.1 创建窗口 import sys from PyQt5.QtWidgets import QApplication, QWidget if __name__ == '__ ...

  5. pyqt5 -——基本功能(HelloWorld)

    一. 简单窗口 这个简单的小例子展示的是一个小窗口.但是我们可以在这个小窗口上面做很多事情,改变大小,最大化,最小化等,这需要很多代码才能实现.这在很多应用中很常见,没必要每次都要重写这部分代码,Qt ...

  6. 五、Pyqt5事件、信号和槽

    PyQt中提供了两种针对事件处理的机制:一种是事件,另一种则是信号和槽. 一.事件 事件处理在PyQt中是比较底层的,常用的事件有键盘事件.鼠标事件.拖放事件.滚轮事件.定时事件.焦点事件.进入和离开 ...

  7. 一、PyQt5基础概念与安装配置

    一.初识PyQt5 对于桌面程序开发,用户图形界面(GUI)的设计非常重要.一款美观.易用的用户界面可以很大程度上提高对使用这的友好度.由于Python最初是作为脚本语言开发,并没有GUI功能.但Py ...

  8. pyQT4和pyQT5的主要模块介绍

    下面简单介绍一下pyQT4和pyQT5的主要模块 pyQT4 的主要模块 QtCore 模块包括了核心的非GUI功能,该模块用来对时间.文件.目录.各种数据类型.流.网址.媒体类型.线程或进程进行处理 ...

  9. PyQt5简介及demo

    PyQt5说明 pyqt5是一套Python绑定Digia QT5应用的框架.它可用于Python 2和3.本教程使用Python 3.Qt库是最强大的GUI库之一.pyqt5的官方网站http:// ...

随机推荐

  1. Beta冲刺测试随笔

    测试工作安排 人员安排: 余文锦,孙劼成,陈富杰,明锐,王彦杰,陈康杰:测试 杨铭海,张鑫宇测试用例的编写 测试工具选择和运用 本来计划Beta冲刺挑选人员进行测试相关的接触和学习并胜任测试工作,但是 ...

  2. 寓教于乐!一款游戏让你成为 Vim 高手!

    我们都知道,Vim 是 Linux 下一种非常重要的文本编辑器,我们可以用它来看代码.改代码,很多高手直接将 Vim 打造成一款强大的 IDE 用来写代码. 但是,对于新手而言,Vim 相对于其它编辑 ...

  3. Java WebService _CXF、Xfire、AXIS2、AXIS1_四种发布方式(优缺点对比)

    xis,axis2,Xfire以及cxf对比 http://ws.apache.org/axis/ http://axis.apache.org/axis2/java/core/ http://xfi ...

  4. Redis持久化机制,优缺点,如何选择合适方式

    一.什么是Redis持久化? 持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失. 二.Redis 的持久化机制是什么?各自的优缺点? Redis 提供两种持久化机制 RDB(默认) 和 ...

  5. jQuery实现全选、反选、删除

    <!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content ...

  6. 00【笔记】 Shiro登陆过滤提示信息

    Shiro登陆过滤 提示信息 package top.yangbuyi.system.shiro; import com.alibaba.fastjson.JSONObject; import org ...

  7. iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 3306 -j DNAT --to-destination 172.17.0.2:3306 ! -i docker0: iptables: No chain/target/match by that name

    今天使用docker运行mysql时报错, 执行命令: docker run --restart=always --name mysql5.7 -p 3306:3306 -v /data/mysql/ ...

  8. Dll的多字节和Unicode

    Dll的多字节和Unicode 分类: MFC2013-10-17 13:00 28人阅读 评论(0) 收藏 举报 dll字符集字符集多字节Unicode 我们定义dll的时候会区分: 字符集:使用多 ...

  9. Vue 封装axios(四种请求)及相关介绍(十三)

    Vue 封装axios(四种请求)及相关介绍 首先axios是基于promise的http库 promise是什么? 1.主要用于异步计算 2.可以将异步操作队列化,按照期望的顺序执行,返回符合预期的 ...

  10. 谈谈如何绕过 TinyPNG 对上传图片数量的限制

    前端er, 又称为切图仔,平时经常需要用 PSD 导出 PNG 或 JPG,但是导出来的的图片一般比较大,往往需要用一些其他工具压缩后再发布到生产环境. 以前常用的做法是,使用 image-webpa ...