【PyQt学习篇 · ⑥】:QWidget - 事件
文章目录
- 事件消息
- 显示和关闭事件
- 移动事件
- 调整大小事件
- 鼠标事件
- 进入和离开事件
- 鼠标按下和释放事件
- 鼠标双击事件
- 鼠标按下移动事件
- 键盘事件
- 焦点事件
- 拖拽事件
- 绘制事件
- 改变事件
- 右键菜单
- 输入法
- 事件转发机制
- 案例一
- 案例二
- 案例三
事件消息
显示和关闭事件
-
showEvent(QShowEvent)
方法:showEvent()
方法在窗口即将显示时被调用。- 它的参数
QShowEvent
可以提供一些有关显示事件的信息。 - 可以通过重写
showEvent()
方法来执行一些在窗口显示前需要初始化的操作。
-
closeEvent(QCloseEvent)
方法:closeEvent()
方法在窗口即将关闭时被调用。- 它的参数
QCloseEvent
可以提供一些有关关闭事件的信息。 - 可以通过重写
closeEvent()
方法来执行一些在窗口关闭前需要处理的操作,例如保存数据或询问用户是否确认关闭窗口。
以下是一个使用showEvent()
和closeEvent()
的示例代码:
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()
的示例代码:
def moveEvent(self, QMoveEvent):
print("窗口被移动了")
运行结果:
调整大小事件
resizeEvent(QResizeEvent)
方法:
resizeEvent()
方法在窗口调整大小时被调用。- 它的参数
QResizeEvent
提供了有关调整大小事件的详细信息,包括窗口的新大小。
以下是一个使用resizeEvent()
的示例代码:
def resizeEvent(self, QResizeEvent):
print('窗口大小被调整了')
运行结果:
鼠标事件
进入和离开事件
-
enterEvent(QEvent)
方法:enterEvent()
方法在鼠标进入窗口时被调用。- 它的参数
QEvent
提供了有关进入事件的详细信息。 - 可以通过重写
enterEvent()
方法来执行一些在鼠标进入窗口时需要的操作,例如更改鼠标的样式或显示一些提示信息。
-
leaveEvent(QEvent)
方法:leaveEvent()
方法在鼠标离开窗口时被调用。- 它的参数
QEvent
提供了有关离开事件的详细信息。 - 可以通过重写
leaveEvent()
方法来执行一些在鼠标离开窗口时需要的操作,例如清除鼠标的样式或隐藏提示信息。
以下是一个使用enterEvent()
和leaveEvent()
的示例代码:
# 鼠标进入控件时背景改为红色
def enterEvent(self, QEnterEvent):
self.setStyleSheet("background-color: red;")
# 鼠标离开控件时背景改为蓝色
def leaveEvent(self, QLeaveEvent):
self.setStyleSheet("background-color: blue;")
运行结果:
如下图所示,左图为鼠标离开控件时,右图为进入控件时。
鼠标按下和释放事件
-
mousePressEvent(QMouseEvent)
方法:mousePressEvent()
方法在鼠标按下时被调用。- 它的参数
QMouseEvent
提供了有关按下事件的详细信息,例如鼠标的位置和按下的按钮。 - 可以通过重写
mousePressEvent()
方法来执行一些在鼠标按下时需要的操作,例如捕获鼠标事件、拖拽操作或执行特定的函数。
-
mouseReleaseEvent(QMouseEvent)
方法:mouseReleaseEvent()
方法在鼠标释放时被调用。- 它的参数
QMouseEvent
提供了有关释放事件的详细信息,例如鼠标的位置和释放的按钮。 - 可以通过重写
mouseReleaseEvent()
方法来执行一些在鼠标释放时需要的操作,例如处理点击事件、完成拖拽操作或执行特定的函数。
以下是一个使用mousePressEvent()
和mouseReleaseEvent()
的示例:
def mousePressEvent(self, QMouseEvent):
print('鼠标被按下')
def mouseReleaseEvent(self, QMouseEvent):
print('鼠标被松开')
运行结果:
鼠标双击事件
mouseDoubleClickEvent(QMouseEvent)
方法:
mouseDoubleClickEvent()
方法在鼠标双击时被调用。- 它的参数
QMouseEvent
提供了有关双击事件的详细信息,例如鼠标的位置和按下的按钮。 - 可以通过重写
mouseDoubleClickEvent()
方法来执行一些在鼠标双击时需要的操作,例如打开新的窗口、执行特定函数或处理双击事件。
以下是一个使用mouseDoubleClickEvent(QMouseEvent)
的示例:
def mouseDoubleClickEvent(self, QMouseEvent):
print("鼠标双击了")
运行结果:
鼠标按下移动事件
mouseMoveEvent(QMouseEvent)
方法:
mouseMoveEvent()
方法在鼠标按下并移动时被调用。- 它的参数
QMouseEvent
提供了有关鼠标移动事件的详细信息,例如鼠标的位置和按下的按钮。 - 可以通过重写
mouseMoveEvent()
方法来执行一些在鼠标按下并移动时需要的操作,例如实现拖拽操作、更新鼠标位置信息或调整窗口大小。
在上一篇文章已介绍其使用方法,在这里就不赘述。
键盘事件
-
keyPressEvent(QKeyEvent)
方法:keyPressEvent()
方法在键盘按下时被调用。- 它的参数
QKeyEvent
提供了有关按键事件的详细信息,例如按键的键码。 - 可以通过重写
keyPressEvent()
方法来执行一些在按键按下时需要的操作,例如捕获按键事件并执行特定的函数或根据按键执行相应的操作。
-
keyReleaseEvent(QKeyEvent)
方法:keyReleaseEvent()
方法在键盘释放时被调用。- 它的参数
QKeyEvent
提供了有关键盘释放事件的详细信息,例如释放的按键的键码。 - 可以通过重写
keyReleaseEvent()
方法来执行一些在按键释放时需要的操作,例如根据按键的组合键执行操作或执行特定函数。
以下是一个使用keyPressEvent()
和keyReleaseEvent()
的示例代码:
def keyPressEvent(self, QKeyEvent):
print('键盘被按下')
def keyReleaseEvent(self, QKeyEvent):
print('键盘松开')
运行结果:
按下两次空格后的结果。
焦点事件
-
focusInEvent(QFocusEvent)
方法:focusInEvent()
方法在控件获取焦点时被调用。- 可以通过重写
focusInEvent()
方法来执行一些在控件获取焦点时需要的操作,例如更改控件的外观或更新与控件相关的属性。
-
focusOutEvent(QFocusEvent)
方法:focusOutEvent()
方法在控件失去焦点时被调用。- 可以通过重写
focusOutEvent()
方法来执行一些在控件失去焦点时需要的操作,例如更新控件的状态或执行校验操作。
拖拽事件
在 PyQT 中,你可以通过在控件上实现一些拖拽事件处理函数来实现拖拽功能,其中包括以下几个 API:
-
dragEnterEvent(QDragEnterEvent)
方法:dragEnterEvent()
方法在拖拽对象进入控件时被调用。- 可以通过重写
dragEnterEvent()
方法来指定控件支持的拖拽操作类型。
-
dragMoveEvent(QDragMoveEvent)
方法:dragMoveEvent()
方法在拖拽对象在控件内移动时被调用。- 可以通过重写
dragMoveEvent()
方法来修改控件的外观以提供反馈。
-
dragLeaveEvent(QDragLeaveEvent)
方法:dragLeaveEvent()
方法在拖拽对象离开控件时被调用。- 可以通过重写
dragLeaveEvent()
方法来恢复控件原来的外观。
-
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)
将事件转发给父类控件来处理。
以下为事件转发的示例:
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_())
运行结果:
当注释掉以下代码:
class Label(QLabel):
pass
#def mousePressEvent(self, QMouseEvent):
#print('标签控件被按下')
在标签位置按下鼠标时,打印“中间控件被按下”,说明鼠标按下事件分发到了父类,即MidWindow
。
运行结果:
案例一
案例一:创建一个窗口包含一个标签。
要求:鼠标进入标签时,展示“欢迎光临”;鼠标离开标签时,展示“谢谢惠顾”。
案例一的代码:
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
以下为案例二的代码:
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()
运行结果:
案例三
案例三:创建一个窗口,用户区支持脱宅。
要求:鼠标点击了用户区拖拽也可以移动窗口。
分析:
- 先获取鼠标按下左键时的位置:mouse_x = evt.globalX()、mouse_y = evt.globalY()
- 再获取窗口的坐上角的位置:origin_x = x()、origin_y = y()
- 鼠标移动的距离:move_x = evt.globalX()-mouse_x、move_y=evt.globalY()-mouse_y
- 窗口该移动的距离:dest_x = origin_x + move_x、dest_y = origin_y + move_y
以下为案例三的代码:
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_())