PYQT5-事件处理机制
PyQt中提供了两种针对事件处理的机制:一种是信号和槽,另一种则是事件;事件处理在PyQt中是比较底层的,这里的事件常见如下类型:
键盘事件、鼠标事件、拖放事件、滚轮事件、定时事件、焦点事件、进入和离开事件(光标移入控件或者移出),移动事件(窗口位置变化),
显示和隐藏事件,窗口事件(窗口是否为当前窗口)、以及常见的Qt事件:Socket事件、剪贴板事件、文字改变事件,布局改变事件;
PyQt提供了5中事件处理和过滤方法,弱到强,其中前两者常用;
(1)重写事件具体的函数(例如:mousePressEvent()/keyPressEvent()…)
(2)重新实现QObject.event()一般用在PyQt没有提供该事件的处理函数的情况下,即添加一个新的事件;
(3)通过事件过滤器
对QObject调用installEventFilter,则相当于为QObject安装了一个事件过滤器;对于QObject的全部事件来说,他们会先传递到事件过滤函数eventFilter中;
在函数中我们可以放弃或者修改某些事件,如果该过滤事件比较多,则会降低性能;
(4)在QApplication中设置事件过滤器
这种方式比前者更强大,QApplication的事件过滤器会捕获所有QObject的事件,且第一个获得事件,即在任意一个事件过滤器之前捕获;
(5)重写QApplication中notify()方法;
使用notify方法来分发事件;想在任意事件处理器之前捕获事件,则唯一方法就是从写notify方法;
1、鼠标按键事件
def mousePressEvent(self, event): print("鼠标按下触发事件") def mouseReleaseEvent (self, event): print("鼠标松开触发事件") def mouseDoubleClickEvent(self, event): print('鼠标双击触发事件')
参数event
方法 | 描叙 |
x()和y() | 返回相对于控件空间的鼠标坐标值 |
pos() | 返回相对于控件空间的QPoint对象 |
localPos() | 返回相对于控件空间的QPointF对象 |
globalX() 和 globalY() | 返回相对于屏幕的x,y 坐标值 |
globalPos() | 返回相对于屏幕的QPoint对象 |
windowPos() | 回相对于窗口的QPointF对象 |
screenPos() | 返回相对于屏幕的QPointF对象 |
button() | 0 - 没有按下鼠标键 |
timestamp() | 返回事件发生的时间 |
2、鼠标指针
def mouseMoveEvent(self, event): print("鼠标移动事件")
默认情况下只有按下鼠标键移动才会触发该事件,设置普通移动也触发该事件setMouseTracking(True);
def enterEvent (self, event): print('鼠标进入控件') def leaveEvent(self, QEvent): print('鼠标离开控件')
3、滚动鼠标
def wheelEvent(self, event): print("鼠标滚轮滚动事件")
4、键盘事件
def keyPressEvent(self, QKeyEvent): print("键盘按下事件") if QKeyEvent.key() == Qt.Key_F5: print('按下F5') def keyReleaseEvent(self, QKeyEvent): print("键盘松开事件") if QKeyEvent.key() == Qt.Key_F6: print("松开F6") #长按会连续触发
5、焦点事件
#设置焦点 self.ui.setFocusPolicy(QtCore.Qt.ClickFocus) def focusInEvent(self, QFocusEvent): print("在焦点") def focusOutEvent(self, QFocusEvent): print("不在焦点")
如果窗口内有其它控件,可以将其它控件设置为NoFocus。
6、示例
重写具体事件和event函数;
from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * import sys class Win(QWidget): def __init__(self,parent=None): super(Win, self).__init__(parent) self.message="" self.btn1=QPushButton("点击1",self) self.btn1.move(20,40) self.btn1.clicked.connect(lambda :self.btnFn(1))#点击按钮,执行btnFn方法 self.btn2 = QPushButton("点击2", self) self.btn2.move(140,40) self.btn2.clicked.connect(lambda: self.btnFn(2)) # 点击按钮,执行btnFn方法 def btnFn(self,flag): if flag==1: print("点击了第一个按钮") else: print("点击了第二个按钮") #上面之前的实例,下面从写按键事件方法 ###第一种方式 def keyPressEvent(self, QKeyEvent):#重写按键事件 if QKeyEvent.key()==Qt.Key_A:#按A建 self.btn1.click() if QKeyEvent.key()==Qt.Key_Tab: print("TABTAB") def closeEvent(self, QCloseEvent):#重写关闭窗口事件 print("重写关闭窗口事件closeEvent") def contextMenuEvent(self, even):#重写上下文菜单事件 menu=QMenu(self) oneAction=menu.addAction("One") oneAction.triggered.connect(self.one) menu.addSeparator()#菜单添加分割线 twoAction=menu.addAction("Two") twoAction.triggered.connect(self.two) menu.exec_(even.globalPos())#事件触发在任意位置 def one(self): print("one") self.message="Menu option One" self.update() def two(self): print("two") self.message="Menu option Two" self.update() def paintEvent(self, event):#重写绘制事件 painter=QPainter(self) painter.setRenderHint(QPainter.TextAntialiasing) painter.drawText(self.rect(),Qt.AlignCenter,self.message) QTimer.singleShot(15000,self.clearMessage)#清空数据 QTimer.singleShot(15000,self.update)#更新当前组件 def clearMessage(self): self.message="" def resizeEvent(self, event):#更新窗体大小事件 self.message="窗口大小调整为:QSize({0},{1})".format(event.size().width(),event.size().height()) self.update() ###第二种方式,一般适用于PyQt没有提供事件处理函数情况,需要自定义事件,例如: #Tab按键不会传递给keyPressEvent; #第二种方式则是重写event函数,所有针对窗口的事件都会传递给event函数,event会根据事件的类型,讲事件分配给不同函数处理; def event(self,event): #?????下面捕获不到tab按键的事件,if判断始终未false,不知道为何,待解决;??? if ( event.type() == QEvent.KeyPress and event.key() == Qt.Key_Tab ): print("Tab") self.message="在event()中捕获Tab按键触发的事件" self.update() return True return QWidget.event(self,event) if __name__=='__main__': app=QApplication(sys.argv) win = Win() win.show() sys.exit(app.exec_())
from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * import sys class Win(QWidget): def __init__(self,parent=None): super(Win, self).__init__(parent) self.resize(400,400) self.btn=QPushButton("按钮",self) self.btn.move(50,50) self.btn.setMinimumWidth(220) self.image=QImage("./image/7.ico") self.label=QLabel('图片',self) self.label.setMinimumWidth(600 ) self.label.setMinimumHeight(400) self.label.move(100,150) self.label.setPixmap(QPixmap(self.image)) #对按钮添加事件过滤器 self.btn.installEventFilter(self) def eventFilter(self,obj, event): if obj==self.btn: if event.type()==QEvent.MouseButtonPress: mouseEvent=QMouseEvent(event) if mouseEvent.buttons()==Qt.LeftButton: self.btn.setText("按鼠标左键缩小图片") transform=QTransform() transform.scale(0.5,0.5)#设置缩放多少倍 self.label.setPixmap(QPixmap.fromImage(self.image.transformed(transform)))#将label中图片设置缩放效果 if mouseEvent.buttons()==Qt.RightButton: self.btn.setText("按鼠标右键放大图片") transform = QTransform() transform.scale(1.5, 1.5)#设置缩放多少倍 self.label.setPixmap(QPixmap.fromImage(self.image.transformed(transform))) return QWidget.eventFilter(self,obj,event) if __name__=='__main__': app=QApplication(sys.argv) win = Win() win.show() sys.exit(app.exec_())
if __name__=='__main__': app=QApplication(sys.argv) win = Win() app.installEventFilter(win) #安装事件过滤器,将前面代码中按钮的installEventFilter注释掉即可 win.show() sys.exit(app.exec_())
评论回复