pyqt5 qwidget有父类窗口如何设置模态_Python+PyQt5进阶(1)

前面10篇介绍了PyQt5的基本控件,从本篇开始深入介绍PyQt5中的一些常用的方法。包括事件处理、对话框、多窗口应用等。

本篇介绍基于窗体的事件处理。窗体的应用程序都是由事件驱动,按钮的点击、鼠标的点击、重绘窗口。有时候我们在处理一些事件,但不想使用默认的事件处理函数,我们自定义处理函数。

应用程序的事件循环

事件主要由操作系统的窗口系统产生,系统产生的事件会进入一个事件队列,由应用程序的事件循环进行处理。在每个主程序的最下面会有一段代码。

app = QApplication(sys.argv)form = MainWindow()form.show()sys.exit(app.exec_())

app是创建的应用程序,最后执行的app.exec()开启了应用程序的事件处理程序。

默认的事件处理函数

在PyQt5中,QEvent类专门用来处理事件。其下有很多子类例如:QKeyEvent、QmouseEvent等。当一个事件触发之后QEvent的子类会实例化一个事件,然后传给产生事件的对象的event()函数处理。

QWidget类是所有界面组件的父类,定义了各种事件的默认处理函数,例如鼠标双击函数QEvent.MouseButtonDblClick,默认的事件处理函数是mouseDoubleClickEvent。每个事件处理函数都会传递一个event参数。常用的默认事件处理函数如下:

  • mousePressEvent():鼠标按键按下
  • mouseReleaseEvent():鼠标按钮释放
  • mouseMoveEvent():鼠标移动
  • mouseDoubleClickEven():鼠标双击
  • closeEvent():窗口关闭

新建一个窗口

桌面内所有的控件都是label。

83f39ad54d6cd0049275d78d906c80b7.png

UI

重写一些事件处理函数

  • paintEvent()

paintEvent()在界面需要绘制时候触发。

def paintEvent(self, event):    filePath = self.currentPath + "Image2.jpg"    painter = QPainter(self)    pic = QPixmap(filePath)    painter.drawPixmap(0, 0, self.width(), self.height(), pic)    super().paintEvent(event)
  • resizeEvent()

resizeEvent()在窗口改变大小时候触发。label标签会在窗口大小改变时候一直显示在窗口的正中间。

def resizeEvent(self, event):    W = self.width()    H = self.height()    labelWidth = self.label.width()    labelHeight = self.label.height()    self.label.setGeometry((W - labelWidth) / 2, (H - labelHeight) / 2, labelWidth, labelHeight)
dd059f75139d8e70202bc588167a803d.gif

resizeEvent

  • closeEvent()

closeEvent()窗口关闭时触发,需要关闭窗口时会弹出一个对话框,是否关闭窗口。如果点击Yes则接受accept这个事件,否则忽略ignore。QMessageBox具体使用后面会介绍。

def closeEvent(self, event):    strTitle = "消息提示框!!!"    strInfo = "closeEvent事件,确定要退出吗?"    btnDia = QMessageBox.NoButton    result = QMessageBox.question(self, strTitle, strInfo, QMessageBox.Yes | QMessageBox.No, btnDia)    if result == QMessageBox.Yes:        event.accept()    else:        event.ignore()
018375457025c8c01cc2b10de0c83b93.gif

关闭窗口

  • mousePressEvent()

mousePressEvent()鼠标点击时候触发。QWidget没有没有clicked信号,所以就不能通过信号和槽处理鼠标的单击,我们可以通过重写mousePressEvent()函数。在鼠标光标处显示当前光标所处的坐标。

7365f104317d38face0a8f1d506131a0.png

Signal/slot

  1. event.pos():获取当的位置。
  2. Qt.LeftButton:返回一个枚举类型Qt.MouseButton,鼠标的哪一个按钮被按下。
  3. x()和y(),获取当前位置的下x,y坐标。
def mousePressEvent(self, event):    mousePosition = event.pos()    if event.button() == Qt.LeftButton:        x = mousePosition.x()        y = mousePosition.y()        self.label_2.setText("(x,y)=(%d,%d)" % (x, y))        rect = self.label_2.geometry()        self.label_2.setGeometry(x, y, rect.width(), rect.height())    super().mousePressEvent(event)
a51fb0f9c39b1af5584574e587abd9a7.gif

鼠标坐标

  • keyPressEvent()

keyPressEvent()键盘按钮被按下时候触发。当按下键盘的按键时候,会在label_3中显示一个导弹。当按下W、A、S、D按键时候将标签移动,就像游戏中的前进、后退、左移、右移。

  1. key():返回值是int类型,与枚举类型Qt.Key的值对应,枚举类型包括键盘上所有按键的枚举值。
def keyPressEvent(self, event):    filePath = self.currentPath + "Image反坦克导弹.png"    self.Pixmap.load(filePath)    width = self.label_3.width()    height = self.label_3.height()    pix = self.Pixmap.scaled(width, height)    self.label_3.setPixmap(pix)    rect = self.label_3.geometry()    if event.key() == Qt.Key_W:        self.label_3.setGeometry(rect.left(), rect.top()-2, rect.width(), rect.height())    if event.key() == Qt.Key_A:        self.label_3.setGeometry(rect.left()-2, rect.top(), rect.width(), rect.height())    if event.key() == Qt.Key_S:        self.label_3.setGeometry(rect.left(), rect.top()+2, rect.width(), rect.height())    if event.key() == Qt.Key_D:        self.label_3.setGeometry(rect.left()+2, rect.top(), rect.width(), rect.height())
0867408e77e37f3d5019de97947ff469.gif

keyPressEvent

事件与信号的关系

在使用一些页面组件时候,我们通常使用其自带的信号,根据信号编写槽函数。但是有些组件却没有我们需要的信号。比如我们如果想让一个label有一个点击的功能,但是label没有clicked信号,我们只能自建一个具有clicked信号功能的标签类。

5e4c3d641b17f1353a125ab085a12ae2.png

label的信号

class newQLabel(QLabel):    doubleClicked = pyqtSignal()    def mouseDoubleClickEvent(self, event):        self.doubleClicked.emit()

自定义一个信号:doubleClicked = pyqtSignal()

自定义一个双击处理函数:def mouseDoubleClickEvent(self, event),当双击时候发射信号。

  • 使用自定义标签类新一个标签newLabel。
self.newLabel = newQLabel(self)self.newLabel.setText("快双击我啊!!!")font = self.newLabel.font()font.setPointSize(18)font.setBold(True)size = self.newLabel.sizeHint()self.newLabel.setGeometry(100, 500, size.width(), size.height())
  • 双击槽函数
self.newLabel.doubleClicked.connect(self.label_doubleClicked)
def label_doubleClicked(self):    self.count += 1    self.newLabel.setText("你双击了Label%d次" % self.count)
8fff94b2cbe5f5506bd5c3cda6f68e1d.gif

双击Label

信号的过滤及拦截

一个组件产生事件首先发送给event()函数,如果没有重写event函数,则会调用默认的事件处理函数,我们可以通过重写event()函数对一些事件做过滤或者屏蔽。最后要调用父类的event函数。不然别的event函数都没办法使用。

def event(self, event):    if event.type() == QEvent.Paint:        self.label.setText("事件函数已被修改,无法显示背景图片")        return True    return super(MainWindow, self).event(event)
f749c44fdf1d30b28032c6f42d9dfba5.png

把paintEvent屏蔽

  • 事件过滤器

事件过滤器可以将一个对象的事件委托给另一个对象来检查并处理。

  1. 被监测的对象使用installEventFilter()将自己注册给监测对象。
  2. 监测对象使用eventFilter()函数,对监测到的对象和事件作出处理。
  • 先安装事件过滤器
self.picture.installEventFilter(self)

self是界面的窗体,把界面窗体设置为事件监测者,picture组件上的事件都会交给窗体处理。

def eventFilter(self, watched, event):    if watched == self.picture:        if event.type() == QEvent.Enter:            self.label_4.setText("鼠标光标进入")        elif event.type() == QEvent.Leave:            self.label_4.setText("鼠标光标移出")        elif event.type() == QEvent.MouseButtonPress:            self.label_4.setText("鼠标按下")        elif event.type() == QEvent.MouseButtonRelease:            self.label_4.setText("鼠标释放")    return super().eventFilter(watched, event)

一个简单的案例介绍事件的使用。如果需要源代码可关注私聊,感谢支持!!!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值