PyQt为事件处理提供了两种机制:高级的信号和槽机制,以及低级的事件处理程序。
PyQt为拦截和处理事件提供了5种不同的方式,这里只介绍最常用的头两种方式。
第一种是重新实现特定事件,如键盘和鼠标事件、重绘事件、尺寸大小改变事件等等,的处理程序。可参见代码示例。
第二种重新实现event()事件处理程序 。因为在任何特殊的事件处理程序被调用前,都会调用event()。重新实现这个方法,可以允许我们处理那些不能在某一特定事件处理程序(如对Tab键焦点转换行为的重新定义)中处理的事件,或者实现那些不存在明确事件处理程序的事件,比如QEvent.ToolBarChange。当需要重新实现这些处理程序时,可以对所有其它不是自己亲自处理的事件调用它们的基类的实现。
import sys
from PyQt5.QtWidgets import QMainWindow, QWidget, QApplication
from PyQt5.QtCore import Qt
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.initUI()
def initUI(self):
self.setWindowTitle("鼠标键盘事件示例")
self.setCentralWidget(QWidget()) # 指定主窗口中心部件
self.statusBar().showMessage("ready") # 状态栏显示信息
self.resize(300, 185)
# 重新实现各事件处理程序
def keyPressEvent(self, event):
key = event.key()
if Qt.Key_A <= key <= Qt.Key_Z:
if event.modifiers() & Qt.ShiftModifier: # Shift 键被按下
self.statusBar().showMessage('"Shift+%s" pressed' % chr(key), 500)
elif event.modifiers() & Qt.ControlModifier: # Ctrl 键被按下
self.statusBar().showMessage('"Control+%s" pressed' % chr(key), 500)
elif event.modifiers() & Qt.AltModifier: # Alt 键被按下
self.statusBar().showMessage('"Alt+%s" pressed' % chr(key), 500)
else:
self.statusBar().showMessage('"%s" pressed' % chr(key), 500)
elif key == Qt.Key_Home:
self.statusBar().showMessage('"Home" pressed', 500)
elif key == Qt.Key_End:
self.statusBar().showMessage('"End" pressed', 500)
elif key == Qt.Key_PageUp:
self.statusBar().showMessage('"PageUp" pressed', 500)
elif key == Qt.Key_PageDown:
self.statusBar().showMessage('"PageDown" pressed', 500)
else: # 其它未设定的情况
QWidget.keyPressEvent(self, event) # 留给基类处理
'''
其它常用按键:
Qt.Key_Escape,Qt.Key_Tab,Qt.Key_Backspace,Qt.Key_Return,Qt.Key_Enter,
Qt.Key_Insert,Qt.Key_Delete,Qt.Key_Pause,Qt.Key_Print,Qt.Key_F1...Qt.Key_F12,
Qt.Key_Space,Qt.Key_0...Qt.Key_9,Qt.Key_Colon,Qt.Key_Semicolon,Qt.Key_Equal
...
'''
def mousePressEvent(self, event): # 鼠标按下事件
pos = event.pos() # 返回鼠标所在点QPoint
self.statusBar().showMessage('Mouse is pressed at (%d,%d) of widget ' % (pos.x(), pos.y()), 500)
globalPos = self.mapToGlobal(pos)
print('Mouse is pressed at (%d,%d) of screen ' % (globalPos.x(), globalPos.y()))
def mouseReleaseEvent(self, event): # 鼠标释放事件
pos = event.pos() # 返回鼠标所在点QPoint
self.statusBar().showMessage('Mouse is released at (%d,%d) of widget ' % (pos.x(), pos.y()), 500)
if event.button() == Qt.LeftButton:
print("左键")
elif event.button() == Qt.MidButton:
print("中键")
elif event.button() == Qt.RightButton:
print("右键")
def mouseDoubleClickEvent(self, event): # 鼠标双击事件
pos = event.pos() # 返回鼠标所在点QPoint
self.statusBar().showMessage('Mouse is double-clicked at (%d,%d) of widget ' % (pos.x(), pos.y()), 500)
def mouseMoveEvent(self, event): # 鼠标移动事件
pos = event.pos() # 返回鼠标所在点QPoint
self.statusBar().showMessage('Mouse is moving at (%d,%d) of widget ' % (pos.x(), pos.y()), 500)
if __name__ == '__main__':
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
键盘事件被频繁处理。例如,按下F1,显示帮助信息;在文本编辑框中,按下回车键,输入焦点自动跳到另一控件。下面详细介绍键盘事件。
1.设置输入焦点
在某一时刻,只有一个控件(或根本没有)可以获得输入焦点。指定输入焦点可使用QWidget的下列方法:
setFocus([reason]) - 如果控件在活动窗口中,调用此方法后,该控件成为输入焦点。reason参数可为QtCore.Qt类中的以下枚举变量:
MouseFocusReason(0):使用鼠标获得焦点;
TabFocusReason(1):按下了键;
BacktabFocusReason(2):按下了+组合键;
ActiveWindowFocusReason(3):窗口变为活动和非活动;
PopupFocusReason(4):打开或关闭弹出窗口;
ShortcutFocusReason(5):按下快捷键;
MenuBarFocusReason(6):通过菜单操作;
OtherFocusReaaon(7):其他方式。
clearFocus() - 去除输入焦点;
hasFocus() - 如果控件是输入焦点,返回True;否则,返回False;
focusWidget() - 返回最后调用setFocus()方法的控件对象;
setFocusProxy() - 指定获得输入焦点的控件对象;
focusProxy() - 返回获得非当前控件的输入焦点的控件对象;
focusNextChild() - 找到下一个可获得输入焦点的控件对象,并设置为输入焦点。相当于按了键。如果有此控件,返回True;否则,返回False;
focusPreviousChild() - 找到上一个可获得输入焦点的控件对象,并设置为输入焦点。相当于按了+键。如果有此控件,返回True;否则,返回False;
focusNextPrevChild() - 如果isnext参数为True,功能相当于focusNextChild();如果isnext参数为False,功能相当于focusPreviousChild();
setTabOrder(,) - 静态函数。用于指定按下键时,输入焦点的移动顺序。component2是当输入焦点在component1是按下键后的输入焦点所在的控件。如果有多个控件,则需要调用多次。例如,指定输入焦点在按下键的变化顺序为widget1->widget2->widget3->widget4,相应的代码为:
QtWidgets.QWidget.setTabOrder(widget1,widget2)
QtWidgets.QWidget.setTabOrder(widget2,widget3)
QtWidgets.QWidget.setTabOrder(widget3,widget4)
setFocusPolicy () - 指定控件如何获得输入焦点。Method可以QtCore.Qt类以一的枚举对象:
nofocus(0):不能获得输入焦点;
TabFocus(1):用键获得;
ClickFocus(2):用点击鼠标获得;
strongFocus(11):用键和点击鼠标获得;
wheelFocus(15):用键、点击鼠标和滚轮获得;
focusPolicy():返回当前获得输入焦点的方式;
grabKeyboard():限定键盘输入。在调用releaseKeyboard()之前,其他控件无法获得输入焦点;
releaseKeyboard():释放之前所作的键盘输入限定。
QApplication类的静态方法focusWidget()返回拥有键盘输入焦点的应用程序顶级窗口。如果还有,返回None.
QWidget类的下列方法可用来处理焦点事件:
focusInEvent(self, event) - 获得焦点时被调用;
focusOutEvent(self,even) - 失去焦点时被调用;
event参数为QFocusEvent类的实例,有以下方法:
gotFocus() - 如果event的类型为QEvent.FocusIn,返回True,否则,返回False;
lostFocus() - 如果event的类型为QEvent.FocusOut,返回True,否则,返回False;
reason() - 返回设置输入焦点的原因。
判断鼠标点击事件——左键按下、中键按下、右键按下、左右键同时按下
from PyQt5 import QtCore, QtGui, QtWidgets, QtMultimedia
class myLabel (QtWidgets.QLabel): # 自定义的QLabel类
def __init__(self, parent=None):
super (myLabel, self).__init__ (parent)
def mousePressEvent(self, e): ##重载一下鼠标点击事件
# 左键按下
if e.buttons () == QtCore.Qt.LeftButton:
self.setText ("左")
# 右键按下
elif e.buttons () == QtCore.Qt.RightButton:
self.setText ("右")
# 中键按下
elif e.buttons () == QtCore.Qt.MidButton:
self.setText ("中")
# 左右键同时按下
elif e.buttons () == QtCore.Qt.LeftButton | QtCore.Qt.RightButton:
self.setText ("左右")
# 左中键同时按下
elif e.buttons () == QtCore.Qt.LeftButton | QtCore.Qt.MidButton:
self.setText ("左中")
# 右中键同时按下
elif e.buttons () == QtCore.Qt.MidButton | QtCore.Qt.RightButton:
self.setText ("右中")
# 左中右键同时按下
elif e.buttons () == QtCore.Qt.LeftButton | QtCore.Qt.MidButton | QtCore.Qt.RightButton:
self.setText ("左中右")
class MyWindow (QtWidgets.QWidget):
def __init__(self):
super (MyWindow, self).__init__ ()
self.label = myLabel ("点我")
self.gridLayout = QtWidgets.QGridLayout (self)
self.gridLayout.addWidget (self.label, 0, 0, 1, 1)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication (sys.argv)
myshow = MyWindow ()
myshow.show ()
sys.exit (app.exec_ ())