【PyQt学习篇 · ⑥】:QWidget - 事件

文章目录

事件消息

显示和关闭事件

  1. showEvent(QShowEvent)方法:

    • showEvent()方法在窗口即将显示时被调用。
    • 它的参数QShowEvent可以提供一些有关显示事件的信息。
    • 可以通过重写showEvent()方法来执行一些在窗口显示前需要初始化的操作。
  2. closeEvent(QCloseEvent)方法:

    • closeEvent()方法在窗口即将关闭时被调用。
    • 它的参数QCloseEvent可以提供一些有关关闭事件的信息。
    • 可以通过重写closeEvent()方法来执行一些在窗口关闭前需要处理的操作,例如保存数据或询问用户是否确认关闭窗口。

以下是一个使用showEvent()closeEvent()的示例代码:

python 复制代码
from PyQt5.QtWidgets import *
import sys


class MyWindow(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

    def showEvent(self, QShowEvent):
        print('窗口被显示出来')

    def closeEvent(self, QCloseEvent):
        print('窗口被关闭')

if __name__ == '__main__':
    app = QApplication(sys.argv)

    window = MyWindow()
    window.show()

    sys.exit(app.exec_())

运行结果:

移动事件

moveEvent(QMoveEvent)方法:

  • moveEvent()方法在窗口移动时被调用。
  • 它的参数QMoveEvent提供了有关移动事件的详细信息,包括窗口的新位置。

以下是一个使用moveEvent()的示例代码:

python 复制代码
def moveEvent(self, QMoveEvent):
    print("窗口被移动了")

运行结果:

调整大小事件

resizeEvent(QResizeEvent)方法:

  • resizeEvent()方法在窗口调整大小时被调用。
  • 它的参数QResizeEvent提供了有关调整大小事件的详细信息,包括窗口的新大小。

以下是一个使用resizeEvent()的示例代码:

python 复制代码
def resizeEvent(self, QResizeEvent):
    print('窗口大小被调整了')

运行结果:

鼠标事件

进入和离开事件

  1. enterEvent(QEvent)方法:

    • enterEvent()方法在鼠标进入窗口时被调用。
    • 它的参数QEvent提供了有关进入事件的详细信息。
    • 可以通过重写enterEvent()方法来执行一些在鼠标进入窗口时需要的操作,例如更改鼠标的样式或显示一些提示信息。
  2. leaveEvent(QEvent)方法:

    • leaveEvent()方法在鼠标离开窗口时被调用。
    • 它的参数QEvent提供了有关离开事件的详细信息。
    • 可以通过重写leaveEvent()方法来执行一些在鼠标离开窗口时需要的操作,例如清除鼠标的样式或隐藏提示信息。

以下是一个使用enterEvent()leaveEvent()的示例代码:

python 复制代码
# 鼠标进入控件时背景改为红色
def enterEvent(self, QEnterEvent):
    self.setStyleSheet("background-color: red;")

# 鼠标离开控件时背景改为蓝色
def leaveEvent(self, QLeaveEvent):
    self.setStyleSheet("background-color: blue;")

运行结果:

如下图所示,左图为鼠标离开控件时,右图为进入控件时。

鼠标按下和释放事件

  1. mousePressEvent(QMouseEvent)方法:

    • mousePressEvent()方法在鼠标按下时被调用。
    • 它的参数QMouseEvent提供了有关按下事件的详细信息,例如鼠标的位置和按下的按钮。
    • 可以通过重写mousePressEvent()方法来执行一些在鼠标按下时需要的操作,例如捕获鼠标事件、拖拽操作或执行特定的函数。
  2. mouseReleaseEvent(QMouseEvent)方法:

    • mouseReleaseEvent()方法在鼠标释放时被调用。
    • 它的参数QMouseEvent提供了有关释放事件的详细信息,例如鼠标的位置和释放的按钮。
    • 可以通过重写mouseReleaseEvent()方法来执行一些在鼠标释放时需要的操作,例如处理点击事件、完成拖拽操作或执行特定的函数。

以下是一个使用mousePressEvent()mouseReleaseEvent()的示例:

python 复制代码
def mousePressEvent(self, QMouseEvent):
    print('鼠标被按下')

def mouseReleaseEvent(self, QMouseEvent):
    print('鼠标被松开')

运行结果:

鼠标双击事件

mouseDoubleClickEvent(QMouseEvent)方法:

  • mouseDoubleClickEvent()方法在鼠标双击时被调用。
  • 它的参数QMouseEvent提供了有关双击事件的详细信息,例如鼠标的位置和按下的按钮。
  • 可以通过重写mouseDoubleClickEvent()方法来执行一些在鼠标双击时需要的操作,例如打开新的窗口、执行特定函数或处理双击事件。

以下是一个使用mouseDoubleClickEvent(QMouseEvent)的示例:

python 复制代码
def mouseDoubleClickEvent(self, QMouseEvent):
    print("鼠标双击了")

运行结果:

鼠标按下移动事件

mouseMoveEvent(QMouseEvent)方法:

  • mouseMoveEvent()方法在鼠标按下并移动时被调用。
  • 它的参数QMouseEvent提供了有关鼠标移动事件的详细信息,例如鼠标的位置和按下的按钮。
  • 可以通过重写mouseMoveEvent()方法来执行一些在鼠标按下并移动时需要的操作,例如实现拖拽操作、更新鼠标位置信息或调整窗口大小。

在上一篇文章已介绍其使用方法,在这里就不赘述。

键盘事件

  1. keyPressEvent(QKeyEvent)方法:

    • keyPressEvent()方法在键盘按下时被调用。
    • 它的参数QKeyEvent提供了有关按键事件的详细信息,例如按键的键码。
    • 可以通过重写keyPressEvent()方法来执行一些在按键按下时需要的操作,例如捕获按键事件并执行特定的函数或根据按键执行相应的操作。
  2. keyReleaseEvent(QKeyEvent)方法:

    • keyReleaseEvent()方法在键盘释放时被调用。
    • 它的参数QKeyEvent提供了有关键盘释放事件的详细信息,例如释放的按键的键码。
    • 可以通过重写keyReleaseEvent()方法来执行一些在按键释放时需要的操作,例如根据按键的组合键执行操作或执行特定函数。

以下是一个使用keyPressEvent()keyReleaseEvent()的示例代码:

python 复制代码
def keyPressEvent(self, QKeyEvent):
    print('键盘被按下')

def keyReleaseEvent(self, QKeyEvent):
    print('键盘松开')

运行结果:

按下两次空格后的结果。

焦点事件

  1. focusInEvent(QFocusEvent) 方法:

    • focusInEvent() 方法在控件获取焦点时被调用。
    • 可以通过重写 focusInEvent() 方法来执行一些在控件获取焦点时需要的操作,例如更改控件的外观或更新与控件相关的属性。
  2. focusOutEvent(QFocusEvent) 方法:

    • focusOutEvent() 方法在控件失去焦点时被调用。
    • 可以通过重写 focusOutEvent() 方法来执行一些在控件失去焦点时需要的操作,例如更新控件的状态或执行校验操作。

拖拽事件

在 PyQT 中,你可以通过在控件上实现一些拖拽事件处理函数来实现拖拽功能,其中包括以下几个 API:

  1. dragEnterEvent(QDragEnterEvent) 方法:

    • dragEnterEvent() 方法在拖拽对象进入控件时被调用。
    • 可以通过重写 dragEnterEvent() 方法来指定控件支持的拖拽操作类型。
  2. dragMoveEvent(QDragMoveEvent) 方法:

    • dragMoveEvent() 方法在拖拽对象在控件内移动时被调用。
    • 可以通过重写 dragMoveEvent() 方法来修改控件的外观以提供反馈。
  3. dragLeaveEvent(QDragLeaveEvent) 方法:

    • dragLeaveEvent() 方法在拖拽对象离开控件时被调用。
    • 可以通过重写 dragLeaveEvent() 方法来恢复控件原来的外观。
  4. dropEvent(QDropEvent) 方法:

    • dropEvent() 方法在拖拽操作完成并释放鼠标时被调用。
    • 可以通过重写 dropEvent() 方法来执行一些特定的功能,例如处理拖拽数据并更新控件状态。

绘制事件

在 PyQT 中,你可以通过在控件上实现一些绘制事件处理函数来实现控件的外观和样式的自定义,其中包括以下几个 API:

paintEvent(QPaintEvent) 方法:

  • paintEvent() 方法在控件需要绘制时被调用。
  • 可以通过重写 paintEvent() 方法来绘制自定义的控件外观和样式。

改变事件

changeEvent(QEvent) 方法:

  • changeEvent() 方法在控件的状态发生改变时被调用。
  • 它的参数 QEvent 提供了有关状态变化的详细信息,例如当前输入法的变化、窗口状态的变化等。
  • 可以通过重写 changeEvent() 方法来响应这些状态变化,并且更新控件的外观和样式。

右键菜单

contextMenuEvent(QContextMenuEvent) 方法:

  • contextMenuEvent() 方法在右键单击控件时被调用。
  • 它的参数 QContextMenuEvent 提供了有关右键单击事件的详细信息。
  • 可以通过重写 contextMenuEvent() 方法来显示一个自定义的右键菜单。

输入法

inputMethodEvent(QInputMethodEvent) 方法:

  • inputMethodEvent() 方法在输入法发生变化时被调用。
  • 它的参数 QInputMethodEvent 提供了有关输入法变化的详细信息。
  • 可以通过重写 inputMethodEvent() 方法来响应输入法变化,并更新控件的外观和样式。

事件转发机制

在 PyQt 中,事件转发(Event Forwarding)机制允许控件将接收到的事件传递给其他控件进行处理。这种机制可以使用 event() 方法来实现。

当一个控件接收到一个事件时,它会首先调用自己的 event() 方法进行事件处理。如果控件不处理该事件,或者希望将事件传递给其他控件进行处理,它可以调用 super().event(event) 将事件转发给父类控件来处理。

以下为事件转发的示例:

python 复制代码
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt
import sys


class Window(QWidget):
    def mousePressEvent(self, QMouseEvent):
        print('顶层窗口被按下')

class MidWindow(QWidget):
    def mousePressEvent(self, QMouseEvent):
        print('中间控件被按下')

class Label(QLabel):
    def mousePressEvent(self, QMouseEvent):
        print('标签控件被按下')

if __name__ == '__main__':
    app = QApplication(sys.argv)

    window = Window()
    window.setWindowTitle('事件转发机制')
    window.resize(500, 500)

    mid_window = MidWindow(window)
    mid_window.resize(300, 300)
    mid_window.setAttribute(Qt.WA_StyledBackground, True)   # 让样式生效
    mid_window.setStyleSheet('background-color: yellow;')

    label = Label(mid_window)
    label.setText('我是标签')
    label.move(100, 100)
    label.setStyleSheet('background-color: red;')

    window.show()

    sys.exit(app.exec_())

运行结果:

当注释掉以下代码:

python 复制代码
class Label(QLabel):
	pass
    #def mousePressEvent(self, QMouseEvent):
        #print('标签控件被按下')

在标签位置按下鼠标时,打印"中间控件被按下",说明鼠标按下事件分发到了父类,即MidWindow

运行结果:

案例一

案例一:创建一个窗口包含一个标签。

要求:鼠标进入标签时,展示"欢迎光临";鼠标离开标签时,展示"谢谢惠顾"。

案例一的代码:

python 复制代码
from PyQt5.QtWidgets import *
import sys

class Label(QLabel):
    def enterEvent(self, QEnterEvent):
        self.setText('欢迎光临')

    def leaveEvent(self, QLeaveEvent):
        self.setText('谢谢惠顾')

if __name__ == '__main__':
    app = QApplication(sys.argv)

    window = QWidget()
    window.setWindowTitle('案例一')
    window.resize(500, 500)

    label = Label(window)
    label.setGeometry(100, 100, 300, 300)
    label.setStyleSheet('background-color: cyan;')

    window.show()
    sys.exit(app.exec_())

运行结果:

案例二

案例二:创建一个窗口,监听用户按键。

要求:

  • 监听用户输入Tab键
  • 监听用户输入Ctrl+S组合键
  • 监听用户输入Ctrl+Shift+A

补充:

修饰键:

  • Qt.NoModifier:没有修饰键
  • Qt.ShiftModifier:Shift键被按下
  • Qt.ControlModifier:Ctrl键被按下
  • Qt.AltModifier:Alt键被按下
  • ......
  • 多个修饰键之间使用或运算

普通键:

  • Qt.Key_xxx

以下为案例二的代码:

python 复制代码
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt
import sys


class Label(QLabel):
    def __init__(self, parent=None):
        super().__init__(parent)

    def keyPressEvent(self, QKeyEvent):
        if QKeyEvent.key() == Qt.Key_Tab:
            self.setText('按下Tab键')

        if QKeyEvent.modifiers() == Qt.ControlModifier and QKeyEvent.key() == Qt.Key_S:
            self.setText('ctrl + s 被点击')

        if QKeyEvent.modifiers() == Qt.ControlModifier | Qt.ShiftModifier and QKeyEvent.key() == Qt.Key_A:
            self.setText('ctrl + Shift + A 被按下')

if __name__ == '__main__':
    app = QApplication(sys.argv)

    window = QWidget()
    window.resize(500, 500)
    window.setWindowTitle('案例二')

    label = Label(window)
    label.resize(300, 300)
    label.move(100, 100)
    label.setContentsMargins(50, 0, 0, 0)
    label.setStyleSheet('background-color: cyan;')
    label.grabKeyboard()    # 捕获键盘

    window.show()

运行结果:

案例三

案例三:创建一个窗口,用户区支持脱宅。

要求:鼠标点击了用户区拖拽也可以移动窗口。

分析:

  1. 先获取鼠标按下左键时的位置:mouse_x = evt.globalX()、mouse_y = evt.globalY()
  2. 再获取窗口的坐上角的位置:origin_x = x()、origin_y = y()
  3. 鼠标移动的距离:move_x = evt.globalX()-mouse_x、move_y=evt.globalY()-mouse_y
  4. 窗口该移动的距离:dest_x = origin_x + move_x、dest_y = origin_y + move_y

以下为案例三的代码:

python 复制代码
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt
import sys

class MyWindow(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.move_Flag = False

    def mousePressEvent(self, QMouseEvent):
        if QMouseEvent.button() == Qt.LeftButton:   # 判断是左键按下
            self.move_Flag = True
            # 鼠标第一次按下时的位置
            self.mouse_x = QMouseEvent.globalX()
            self.mouse_y = QMouseEvent.globalY()

            # 窗口左上角的坐标
            self.origin_x = self.x()
            self.origin_y = self.y()

    def mouseMoveEvent(self, QMouseEvent):
        if self.move_Flag:
            # 计算移动量
            move_x = QMouseEvent.globalX() - self.mouse_x
            move_y = QMouseEvent.globalY() - self.mouse_y

            # 移动的位置
            dest_x = self.origin_x + move_x
            dest_y = self.origin_y + move_y

            self.move(dest_x, dest_y)

    def mouseReleaseEvent(self, QMouseEvent):
        self.move_Flage = False


if __name__ == '__main__':
    app = QApplication(sys.argv)

    window = MyWindow()
    window.resize(300, 300)
    window.setWindowTitle('案例三')

    window.show()
    sys.exit(app.exec_())
相关推荐
深度学习lover1 小时前
<项目代码>YOLOv8 苹果腐烂识别<目标检测>
人工智能·python·yolo·目标检测·计算机视觉·苹果腐烂识别
API快乐传递者2 小时前
淘宝反爬虫机制的主要手段有哪些?
爬虫·python
阡之尘埃4 小时前
Python数据分析案例61——信贷风控评分卡模型(A卡)(scorecardpy 全面解析)
人工智能·python·机器学习·数据分析·智能风控·信贷风控
丕羽7 小时前
【Pytorch】基本语法
人工智能·pytorch·python
bryant_meng7 小时前
【python】Distribution
开发语言·python·分布函数·常用分布
m0_594526309 小时前
Python批量合并多个PDF
java·python·pdf
工业互联网专业9 小时前
Python毕业设计选题:基于Hadoop的租房数据分析系统的设计与实现
vue.js·hadoop·python·flask·毕业设计·源码·课程设计
钱钱钱端9 小时前
【压力测试】如何确定系统最大并发用户数?
自动化测试·软件测试·python·职场和发展·压力测试·postman
慕卿扬9 小时前
基于python的机器学习(二)—— 使用Scikit-learn库
笔记·python·学习·机器学习·scikit-learn
Json____9 小时前
python的安装环境Miniconda(Conda 命令管理依赖配置)
开发语言·python·conda·miniconda