使用 PyQt 快速搭建带有 GUI 的应用(5)–鼠标悬浮操作

  • A+
所属分类:Python库介绍
摘要本文会介绍 PyQt 中鼠标悬停触发事件的做法。会通过两个例子,说明如何在鼠标悬停在不同的组件上时,触发不同的事件。

简介

在这个例子中,我们介绍两个在 PyQt 中触发事件的方式,分别是「鼠标点击」触发和「鼠标悬浮」触发。所谓「鼠标悬浮」指鼠标滑过某个区域时候来触发事件。

不像是「鼠标点击」进行触发可以使用 .clicked.connect,这里的「鼠标悬浮」我们需要对指定的组件使用 installEventFilter,接着在下面定义 eventFilter,最后根据 QEvent.EnterQEvent.Leave 来判断鼠标的进入和离开。(后面会有例子)

这里鼠标悬浮触发事件,主要参考自下面的例子,Mouseover event for a PyQT5 Label

 

简单的鼠标悬浮触发例子

首先我们看一个简单的例子,我们定义一个 QLabel 的小组件,并实现当鼠标移动在上面和离开的时候打印文字。完整的代码如下所示:

  1. from PyQt5.QtWidgets import *
  2. from PyQt5.QtGui import *
  3. from PyQt5.QtCore import *
  4. import sys
  5. class mouseoverEvent(QWidget):
  6.     def __init__(self):
  7.         super().__init__()
  8.         self.initUI()
  9.     def initUI(self):
  10.         self.lbl=QLabel(self)
  11.         self.lbl.setText("Hover over me to stop the program") # QLabel 显示的文字
  12.         self.lbl.installEventFilter(self# 对 QLabel 设置 EventFilter
  13.         self.setGeometry(1000, 30, 300, 100) # 设置 QLabel 的大小
  14.         self.show()
  15.     def eventFilter(selfobject, event):
  16.         if event.type() == QEvent.Enter: # 当鼠标进入时
  17.             print('Mouse is over the label, Object Text, {}'.format(object.text()))
  18.             return True
  19.         elif event.type() == QEvent.Leave: # 当鼠标离开时
  20.             print('Mouse is not over the label')
  21.         return False
  22. if __name__ == '__main__':
  23.     app = QApplication(sys.argv)
  24.     ex = mouseoverEvent()
  25.     sys.exit(app.exec_())

我们对上面的代码进行简单的解释:

  • 我们在 initUI 主要构建的界面相关的代码,同时对 QLabel 进行 EventFilter 的绑定;
  • 详细的 eventFilter 定义如下,当 event.typeQEvent.Enter 的时候,会触发 print 的内容,其中 object.text() 会是组件的文字内容。
  • eventFilter 中,这里的 return Truereturn False 是一定需要的。

最终的效果如下所示,鼠标进入和离开都会有内容打印出来

使用 PyQt 快速搭建带有 GUI 的应用(5)--鼠标悬浮操作

 

鼠标点击与悬浮触发例子

上面是一个比较简单的鼠标进入和离开触发 event 的例子。现在我们的需求会更加复杂一些,我们希望移动在不同的 Label 上的时候,触发不同的事件。这个我们可以通过 object.text() 的这种方式进行判断。我们看下面这个例子。

界面设计

我们使用 QtDesigner 来设计一个非常简单的界面。页面由左右两个部分组成,左侧是按钮,右侧是 stacked widget。把鼠标放在不同的按钮上,右侧会出现不同的 page

总体界面如下所示,这一部分就不放代码了,可以自己在 QtDesigner 中简单设计一下即可。

使用 PyQt 快速搭建带有 GUI 的应用(5)--鼠标悬浮操作

在这里,stacked widget 中共有 4 个page,按顺序分别是,「首页」,「第一页」,「第二页」,「第三页」。如下所示:

使用 PyQt 快速搭建带有 GUI 的应用(5)--鼠标悬浮操作

 

功能部分代码编写

上面我们完成了界面的设计,这里我们完成主要功能模块的设计。完整的代码如下所示:

  1. import os
  2. import sys
  3. from PyQt5.QtCore import QEvent
  4. from PyQt5.uic import loadUi
  5. from PyQt5.QtWidgets import QApplication, QMainWindow
  6. class HoverApp(QMainWindow):
  7.     """鼠标滑过, 触发动作
  8.     """
  9.     def __init__(self, parent=None) -> None:
  10.         super().__init__(parent)
  11.         loadUi(os.path.abspath(os.path.join(os.path.dirname(__file__), 'pp.ui')), self)
  12.         # 绑定按钮
  13.         self.pushButton.installEventFilter(self)
  14.         self.pushButton_3.installEventFilter(self)
  15.         # 鼠标移动与离开 2
  16.         self.pushButton_2.clicked.connect(self.click_switch_tab) # 点击按钮
  17.     def eventFilter(selfobject, event):
  18.         if hasattr(object, 'text'): # 确认一下 object 是否有 text 的属性
  19.             if event.type() == QEvent.Enter: # 鼠标进入
  20.                 if object.text() == '悬停显示第一页': # 判断鼠标进入哪一个 QPushButton
  21.                     self.hover_switch_tab_1(enter=True)
  22.                 elif object.text() == '悬停显示第二页':
  23.                     self.hover_switch_tab_2(enter=True)
  24.                 return True
  25.             elif event.type() == QEvent.Leave: # 鼠标离开
  26.                 if object.text() == '悬停显示第一页':
  27.                     self.hover_switch_tab_1(enter=False)
  28.                 elif object.text() == '悬停显示第二页':
  29.                     self.hover_switch_tab_2(enter=False)
  30.                 return True
  31.         return False
  32.     def hover_switch_tab_1(self, enter=False):
  33.         """悬停显示页面 1, 移走时候显示首页
  34.         """
  35.         if enter: # 进入时
  36.             print('切换到第一页')
  37.             self.stackedWidget.setCurrentIndex(1)
  38.         else:
  39.             print('切换回首页')
  40.             self.stackedWidget.setCurrentIndex(0) # 首页下标是 0
  41.     def hover_switch_tab_2(self, enter=False):
  42.         """悬停显示页面 2, 移走时候显示首页
  43.         """
  44.         if enter: # 进入时
  45.             print('切换到第二页')
  46.             self.stackedWidget.setCurrentIndex(2)
  47.         else:
  48.             print('切换回首页')
  49.             self.stackedWidget.setCurrentIndex(0) # 首页下标是 0    
  50.     def click_switch_tab(self):
  51.         """点击切换到第三页
  52.         """
  53.         print('切换到第三页.')
  54.         self.stackedWidget.setCurrentIndex(3)

主要看上面的eventFilter,根据 event.typeobject.text 来判断鼠标进入了哪一个组件,从而触发不同的效果。

切换 stackedWidget 是通过 self.stackedWidget.setCurrentIndex 来实现的,第一个 page 的 ID 是从 0 开始的。

这里还需要有一个注意的是,上面绑定按钮的时候,例如 self.pushButtonself.pushButton_3 是 组件的 object_name,这个可以从 QtDesigner 中查询到。

最终的效果如下所示,可以看到:

  • 当鼠标悬停在「悬停显示第一页」时,会显示第一页,离开则显示首页;
  • 当鼠标悬停在「悬停显示第二页」时,会显示第二页,离开则显示首页;
  • 当鼠标悬停在「点击显示第三页」时,会显示第三页
使用 PyQt 快速搭建带有 GUI 的应用(5)--鼠标悬浮操作
  • 微信公众号
  • 关注微信公众号
  • weinxin
  • QQ群
  • 我们的QQ群号
  • weinxin
王 茂南

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: