事件就是由窗口、控件本身或者PyQt5自身产生的,配合用户动作的各种响应。“事件”和“信号”非常相似,但请不要归为一类。

事件类型种类繁多,这里主要介绍一些常用的:窗口关闭事件处理、鼠标事件处理以及键盘事件处理。

17.1 窗口关闭事件

当笔者在博客编辑器中进行写作时,若没有点击保存直接关闭窗口时(触发窗口关闭事件),会出现弹框询问是否确定离开:

我们来用PyQt5实现类似功能,代码如下:

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QTextEdit, QPushButton, QMessageBox, QVBoxLayoutclass Demo(QWidget):def __init__(self):super(Demo, self).__init__()self.is_saved = True                                            # 1self.textedit = QTextEdit(self)                                 # 2self.textedit.textChanged.connect(self.on_textchanged_func)self.button = QPushButton('Save', self)                         # 3self.button.clicked.connect(self.on_clicked_func)self.v_layout = QVBoxLayout()   self.v_layout.addWidget(self.textedit)self.v_layout.addWidget(self.button)self.setLayout(self.v_layout)def on_textchanged_func(self):                      if self.textedit.toPlainText(): self.is_saved = Falseelse:self.is_saved = Truedef on_clicked_func(self):self.save_func(self.textedit.toPlainText())self.is_saved = Truedef save_func(self, text):          with open('saved.txt', 'w') as f:f.write(text)def closeEvent(self, QCloseEvent):                                  # 4if not self.is_saved:choice = QMessageBox.question(self, '', 'Do you want to save the text?',QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)if choice == QMessageBox.Yes:self.save_func(self.textedit.toPlainText())QCloseEvent.accept()elif choice == QMessageBox.No:QCloseEvent.accept()else:QCloseEvent.ignore()if __name__ == '__main__':app = QApplication(sys.argv)demo = Demo()demo.show()sys.exit(app.exec_())

1. is_saved变量用于记录用户是否已经进行保存;

2. 实例化一个QTextEdit控件用于文本编辑,将其textChanged信号和自定义的槽函数连接起来:

def on_textchanged_func(self):                      if self.textedit.toPlainText(): self.is_saved = Falseelse:self.is_saved = True

在槽函数中我们判断在每次文本内容发生变化时,textedit中是否还有文本,若有的话则将is_saved变量设为False,即未保存;若无文本,则将其设为True(如果没有文本的话,那可以直接关闭窗口,程序不会询问是否需要保存,因为没必要)。

3. 实例化一个按钮用于保存操作,将clicked信号与自定义的槽函数进行连接:

def on_clicked_func(self):self.save_func(self.textedit.toPlainText())self.is_saved = True

每次点击该按钮就进行保存,不管文本编辑框中是否有文本,文本保存通过save_fcun()函数完成:

def save_func(self, text):          with open('saved.txt', 'w') as f:f.write(text)

我们将内容保存在当前目录下的saved.txt函数中。PyQt5提供一个QFileDialog类可以让我们更好的完成保存操作,后续章节会涉及,这里只是先简单的完成下保存功能。

4. 这里我们重新定义了QWidget的窗口关闭函数closeEvent(),如果用户还没有进行保存,则弹出一个QMessageBox窗口询问是否保存,若用户点击Yes,则调用save_func()函数进行保存,然后通过accept()方法来接收关闭窗口操作,窗口随之关闭;若点击No,则不进行保存,但同样得关闭窗口;若点击cancel,也不进行保存,并通过ignore()方法来忽略这次关闭窗口的操作。

运行截图如下,输入la vie est belle后不点击Save按钮,直接关闭窗口,则会出现弹窗询问是否需要保存:

我们点击Yes后,则窗口关闭,在项目路径下出现一个‘saved.txt’文件,里面的文本正是我们之前所输入的la vie est belle:

17.2 鼠标事件

鼠标移动、按下或者释放动作都会唤起相应的鼠标事件:

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayoutclass Demo(QWidget):def __init__(self):super(Demo, self).__init__()self.button_label = QLabel('No Button Pressed', self)              # 1self.xy_label = QLabel('x:0, y:0', self)                           # 2self.global_xy_label = QLabel('global x:0, global y:0', self)      # 3self.button_label.setAlignment(Qt.AlignCenter)self.xy_label.setAlignment(Qt.AlignCenter)self.global_xy_label.setAlignment(Qt.AlignCenter)self.v_layout = QVBoxLayout()self.v_layout.addWidget(self.button_label)self.v_layout.addWidget(self.xy_label)self.v_layout.addWidget(self.global_xy_label)self.setLayout(self.v_layout)self.resize(300, 300)                                          self.setMouseTracking(True)                                        # 4def mouseMoveEvent(self, QMouseEvent):                                 # 5x = QMouseEvent.x()y = QMouseEvent.y()global_x = QMouseEvent.globalX()global_y = QMouseEvent.globalY()self.xy_label.setText('x:{}, y:{}'.format(x, y))self.global_xy_label.setText('global x:{}, global y:{}'.format(global_x, global_y))def mousePressEvent(self, QMouseEvent):                                # 6if QMouseEvent.button() == Qt.LeftButton:self.button_label.setText('Left Button Pressed')elif QMouseEvent.button() == Qt.MidButton:self.button_label.setText('Middle Button Pressed')elif QMouseEvent.button() == Qt.RightButton:self.button_label.setText('Right Button Pressed')def mouseReleaseEvent(self, QMouseEvent):                              # 7if QMouseEvent.button() == Qt.LeftButton:self.button_label.setText('Left Button Released')elif QMouseEvent.button() == Qt.MidButton:self.button_label.setText('Middle Button Released')elif QMouseEvent.button() == Qt.RightButton:self.button_label.setText('Right Button Released')def mouseDoubleClickEvent(self, QMouseEvent):                          # 8if QMouseEvent.button() == Qt.LeftButton:self.button_label.setText('Left Button Double Clikced')elif QMouseEvent.button() == Qt.MidButton:self.button_label.setText('Middle Button Double Clicked')elif QMouseEvent.button() == Qt.RightButton:self.button_label.setText('Right Button Double Clikced')if __name__ == '__main__':app = QApplication(sys.argv)demo = Demo()demo.show()sys.exit(app.exec_())

1. button_label用来显示鼠标的点击和释放动作;

2. xy_label用于记录鼠标相对于QWidget窗口的坐标;

3. global_xy_label用于记录鼠标相对于显示屏屏幕的坐标;

4. setMouseTracking(True)方法可以让窗口始终追踪鼠标,否则只能每次等鼠标被点击后,窗口才会开始记录鼠标的动作变化;而鼠标释放后,窗口又会不进行记录了,这样比较麻烦。

5. mouseMoveEvent()为鼠标移动时所触发的响应函数,在函数中,我们通过x()和y()方法获取鼠标相对于QWidget窗口的坐标,用globalX()和globalY()方法获取鼠标相对于显示屏屏幕的坐标;

6. mousePressEvent()为鼠标被按下时所触发的响应函数,在函数中,我们通过button()方法来确认被按下的键,然后用button_label显示被按下的键;

7. mouseReleaseEvent()为鼠标释放时所触发的响应函数,同理,在函数中,我们通过button()方法来确认被释放的键,然后用button_label显示被释放的键;

8. mouseDoubleClickEvent()为鼠标被双击时所触发的响应函数,同理,在函数中,我们通过button()方法来确认被双击的键,然后用button_label显示被双击的键;

运行截图如下,刚开始坐标都为(0, 0),鼠标也没有键被按下:

之后我们移动鼠标,发现坐标值随之变化:

按下鼠标左键,button_label显示被按下的键:

释放左键后,文本信息变化,显示被释放的键:

双击鼠标左键,同样显示对应信息:

​17.3 键盘事件

每当用户按下或释放键盘上的任意键时都会触发键盘事件:

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayoutclass Demo(QWidget):def __init__(self):super(Demo, self).__init__()self.pic_label = QLabel(self)                                   # 1self.pic_label.setPixmap(QPixmap('images/keyboard.png'))self.pic_label.setAlignment(Qt.AlignCenter)self.key_label = QLabel('No Key Pressed', self)                 # 2self.key_label.setAlignment(Qt.AlignCenter)self.v_layout = QVBoxLayout()self.v_layout.addWidget(self.pic_label)self.v_layout.addWidget(self.key_label)self.setLayout(self.v_layout)def keyPressEvent(self, QKeyEvent):                                 # 3if QKeyEvent.key() == Qt.Key_Up:self.pic_label.setPixmap(QPixmap('images/up.png'))self.key_label.setText('Key Up Pressed')elif QKeyEvent.key() == Qt.Key_Down:self.pic_label.setPixmap(QPixmap('images/down.png'))self.key_label.setText('Key Down Pressed')elif QKeyEvent.key() == Qt.Key_Left:self.pic_label.setPixmap(QPixmap('images/left.png'))self.key_label.setText('Key Left Pressed')elif QKeyEvent.key() == Qt.Key_Right:self.pic_label.setPixmap(QPixmap('images/right.png'))self.key_label.setText('Key Right Pressed')def keyReleaseEvent(self, QKeyEvent):                               # 4self.pic_label.setPixmap(QPixmap('images/keyboard.png'))self.key_label.setText('Key Released')if __name__ == '__main__':app = QApplication(sys.argv)demo = Demo()demo.show()sys.exit(app.exec_())

1. pic_label用于设置图片,先将初始化的图片设为keyboard.png;

2. key_label用于记录按键状态;

3. keyPressEvent()为键盘某个键被按下时所触发的响应函数,在这个函数中我们判断被按下的键种类,并将pic_label设为相应的箭头图片,将key_label设为相应的文本;

4. keyReleasedEvent()在键盘上的任意键被释放时所触发的响应函数,在这个函数中,我们将pic_label设为初始图片keyboard.png,并将key_label文本设为‘Key Released'。

注:可以在QtAssistant中输入Qt::Key找到所有键盘值:

图片下载地址:

  • keyboard.png: https://www.easyicon.net/download/png/1197696/64/
  • up.png: https://www.easyicon.net/download/png/16090/32/
  • down.png: https://www.easyicon.net/download/png/6294/32/
  • right.png: https://www.easyicon.net/download/png/4515/32/
  • left.png: https://www.easyicon.net/download/png/14605/32/

运行截图如下,初始状态:

当按下向上键后:

释放后:

关于事件的进阶用法,请大家阅读:

《PyQt5高级编程实战》事件处理深入应用_la_vie_est_belle的博客-CSDN博客​pyqt5.blog.csdn.net

​17.4 小结:

1. 本章一共介绍了三种事件类型:窗口关闭事件、鼠标事件和键盘事件,分别是对窗口关闭、鼠标和键盘动作的响应。当然事件类型还有很多,之后章节会有涉及;

2. setMouseTracking(True)可以让窗口时刻追踪鼠标,而不需要在鼠标被按下时才会进行追踪;

3. x()和y()获取鼠标相对于窗口部件的坐标值,而globalX()和globalY()获取鼠标相对于显示屏窗口的坐标值;

4. button()方法用于获取鼠标被按下或释放的键,key()方法用于获取键盘被按下或释放的键。

pyqt5 实现右键自定义_《快速掌握PyQt5》第十七章 事件处理相关推荐

  1. 学pyqt5之前需要学python吗_快速学习pyqt5(1)--入门

    学习于:PyQt5图形界面编程 想要系统学习的同学建议可以去这个专栏好好学习,没有任何语言基础和计算机基础的也建议直接去看那个专栏.我这里是有java基础了,所以就不重复,针对快速学习使用. 学习这个 ...

  2. SPI 读取不同长度 寄存器_正点原子Linux第二十七章SPI实验

    1)资料下载:点击资料即可下载 2)对正点原子Linux感兴趣的同学可以加群讨论:935446741 3)关注正点原子公众号,获取最新资料更新 第二十七章SPI实验 同I2C一样,SPI是很常用的通信 ...

  3. python pyqt5 线程 暂停 重启_如何在PyQT5中暂停/播放线程?

    我正在用PyQT5制作一个简单的GUI程序.在 但现在我遇到了一些关于线的问题.在 我只做了一个简单的测试程序,比如bottom: 该程序只是试图将数字附加到textbox,但它崩溃了.在 我不知道为 ...

  4. 柏西机器人_第四百六十七章 次元声波_我的手机有外星游戏最新章节

    第四百六十七章 次元声波 "我是星兽一族!"小星兽自豪地说道. 希尔柏西一愣,"星兽?怎么可能!" 作为见多识广的贝硫多拉高层,希尔柏西当然知道星兽一族的情况, ...

  5. 《快速掌握PyQt5》

    写在前面: 因为太喜欢Python和Qt了,所以想开始慢慢写一些有关PyQt5的知识点.刚开始会介绍各个控件的使用,之后会进行实战操作,相信学完本系列对大家的兼职/外快事业会有帮助.所有的篇章不会有太 ...

  6. 《快速掌握PyQt5》第二十三章 主窗口QMainWindow

    第二十三章 主窗口QMainWindow 23.1 记事本应用 23.3 程序启动画面QSplashScreen 23.2 小结 <快速掌握PyQt5>专栏已整理成书出版,书名为<P ...

  7. 《快速掌握PyQt5》第二章 信号与槽——裁判鸣枪与选手开跑

    第二章  信号与槽--裁判鸣枪与选手开跑 2.1 通过按钮来改变文本(一个信号连接一个槽) 2.2 多个信号连接同一个槽 2.3 一个信号与另外一个信号连接 2. 4 一个信号连接多个槽 2.5 自定 ...

  8. 《快速掌握PyQt5》专栏整理成书出版啦!

    首先非常感谢大家对<快速掌握PyQt5>专栏的喜爱与支持!该专栏现已整理成书出版,书名为<PyQt编程快速上手>. 本书内容在专栏内容的基础上进行了多方面的优化,内容更加丰富, ...

  9. 《快速掌握PyQt5》第三十六章 用PyQtGraph绘制可视化数据图表

    第三十六章 用PyQtGraph绘制可视化数据图表 36.1 下载PyQtGraph 36.2 基础知识与用法 36.3 将PyQtGraph嵌入到PyQt5中 36.4 小结 <快速掌握PyQ ...

最新文章

  1. JPA关系映射之one-to-many和many-to-one
  2. SAP 730模糊查询时不可以输入连续的汉字问题解决方案
  3. 初学python之路-day18
  4. OpenCV展开二维相位图
  5. redis实现轮询算法_基于zookeeper或redis实现分布式锁
  6. 优化Hibernate所鼓励的7大措施:
  7. app传输数据到php,安卓app客户端和使用php的服务器端数据交互
  8. git bash here创建项目无法选择m_版本控制Git基础及使用详解
  9. 【转】Unity3D研究院之设置自动旋转屏幕默认旋转方向
  10. linux内核之进程管理详解
  11. 计算机考研复试【英语面试题汇总】
  12. 安川机器人io对照表_安川机器人IO信号对照表.pdf
  13. 酒店计算机应用例子,酒店管理系统_计算机应用专业毕业论文
  14. python自动排版公众号_GitHub - qfwc258/maxpress: MaxPress:MarkDown+Python实现微信公众号一键排版...
  15. 离散数学 用c++实现离散数学逻辑推理
  16. 阿里大数据之路:数据管理篇大总结
  17. MEC的云边协同分析
  18. openbmc-web3:添加语言
  19. 甲乙轮流抛硬币,正面胜,先抛的人优势多大?
  20. 安卓屏幕适配——pt适配,将pt作为宽度百分比单位

热门文章

  1. 2.4.4 案例理解4种事务的隔离级别
  2. LVS负载均衡群集部署之——NAT模式的介绍及搭建步骤
  3. 病毒源代码Java_病毒代码_bat病毒代码_java病毒代码(5)
  4. nodejs源码_格物致知记一次nodejs源码分析的经历
  5. html lt;ligt; 属性,HTML文件中lt;HRgt;标签各个属性的作用是什么?
  6. 2021云栖大会丨首批阿里云计算巢认证合作伙伴获得授牌,阿里云与合作伙伴共筑云上生态
  7. 哈啰在分布式消息治理和微服务治理中的实践
  8. 大型企业多账号管理“安全心法”
  9. DataWorks数据建模公开课上线啦!
  10. 通过Kubernetes安全高效管理边缘节点,ACK@Edge年度重磅发布