PyQt中实现自定义工具提示ToolTip的方法详解

作者:之一Yo 时间:2023-11-09 13:34:56 

前言

Qt 自带的工具提示样式不太好看,就算加了样式表也时不时会失效,同时工具提示没有阴影,看起来就更难受了。所以本篇博客将会介绍自定义工具提示的方法,效果如下图所示:

PyQt中实现自定义工具提示ToolTip的方法详解

实现过程

工具提示其实就是一个带了标签的窗口,为了给工具提示加上阴影,只要给窗口设置 QGraphicsShadowEffect 即可。同时 QToolTip 弹出之后不会一直卡在界面上,一段时间后就会消失,所以我们应该给自定义的工具提示加上一个 QTimer,时间溢出之后就隐藏工具提示。

# coding:utf-8
from PyQt5.QtCore import QFile, QPropertyAnimation, QTimer, Qt
from PyQt5.QtGui import QColor
from PyQt5.QtWidgets import (QApplication, QFrame, QGraphicsDropShadowEffect,
                            QHBoxLayout, QLabel)

class ToolTip(QFrame):

def __init__(self, text='', parent=None):
       super().__init__(parent=parent)
       self.__text = text
       self.__duration = 1000
       self.timer = QTimer(self)
       self.hBox = QHBoxLayout(self)
       self.label = QLabel(text, self)
       self.ani = QPropertyAnimation(self, b'windowOpacity', self)

# set layout
       self.hBox.addWidget(self.label)
       self.hBox.setContentsMargins(10, 7, 10, 7)

# add shadow
       self.shadowEffect = QGraphicsDropShadowEffect(self)
       self.shadowEffect.setBlurRadius(32)
       self.shadowEffect.setColor(QColor(0, 0, 0, 60))
       self.shadowEffect.setOffset(0, 5)
       self.setGraphicsEffect(self.shadowEffect)

self.timer.setSingleShot(True)
       self.timer.timeout.connect(self.hide)

# set style
       self.setAttribute(Qt.WA_StyledBackground)
       self.setDarkTheme(False)
       self.__setQss()

def text(self):
       return self.__text

def setText(self, text: str):
       """ set text on tooltip """
       self.__text = text
       self.label.setText(text)
       self.label.adjustSize()
       self.adjustSize()

def duration(self):
       return self.__duration

def setDuration(self, duration: int):
       """ set tooltip duration in milliseconds """
       self.__duration = abs(duration)

def __setQss(self):
       """ set style sheet """
       f = QFile("resource/tooltip.qss")
       f.open(QFile.ReadOnly)
       self.setStyleSheet(str(f.readAll(), encoding='utf-8'))
       f.close()

self.label.adjustSize()
       self.adjustSize()

def setDarkTheme(self, dark=False):
       """ set dark theme """
       dark = 'true' if dark else 'false'
       self.setProperty('dark', dark)
       self.label.setProperty('dark', dark)
       self.setStyle(QApplication.style())

def showEvent(self, e):
       self.timer.stop()
       self.timer.start(self.__duration)
       super().showEvent(e)

def hideEvent(self, e):
       self.timer.stop()
       super().hideEvent(e)

工具提示继承自 QFrame 的原因是我们需要设置边框样式,样式表如下所示,支持亮暗两种主题:

ToolTip[dark="false"] {
   border: 1px solid rgba(0, 0, 0, 0.06);
   border-radius: 5px;
   background-color: rgb(243, 243, 243);
}

ToolTip[dark="true"] {
   border: 1px solid rgb(28, 28, 28);
   border-radius: 5px;
   background-color: rgb(43, 43, 43);
}

QLabel {
   background-color: transparent;
   font: 15px 'Segoe UI', 'Microsoft YaHei';
}

QLabel[dark="false"] {
   color: black;
}

QLabel[dark="true"] {
   color: white;
}

测试

下述代码的运行效果就是动图中所示的样子,只要给想要设置工具提示的部件安装上事件过滤器,就能将 QToolTip 替换成自定义的工具提示:

# coding:utf-8
import sys
from PyQt5.QtCore import QEvent, QPoint
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout

from tool_tip import ToolTip

class Demo(QWidget):

def __init__(self):
       super().__init__()
       self.hBox = QHBoxLayout(self)
       self.button1 = QPushButton('キラキラ', self)
       self.button2 = QPushButton('食べた愛', self)
       self._toolTip = ToolTip(parent=self)
       # self._tooltip.setDarkTheme(True)

self.button1.setToolTip('aiko - キラキラ ✨')
       self.button2.setToolTip('aiko - 食べた愛 🥰')
       self.button1.setToolTipDuration(1000)
       self.button2.setToolTipDuration(5000)

self.button1.installEventFilter(self)
       self.button2.installEventFilter(self)

self.hBox.setContentsMargins(30, 30, 30, 30)
       self.hBox.setSpacing(20)
       self.hBox.addWidget(self.button1)
       self.hBox.addWidget(self.button2)

self.resize(600, 300)
       self._toolTip.hide()

with open('resource/demo.qss', encoding='utf-8') as f:
           self.setStyleSheet(f.read())

def eventFilter(self, obj, e: QEvent):
       if obj is self:
           return super().eventFilter(obj, e)

tip = self._toolTip
       if e.type() == QEvent.Enter:
           tip.setText(obj.toolTip())
           tip.setDuration(obj.toolTipDuration())

pos = obj.mapTo(self, QPoint(0, 0))
           x = pos.x() + obj.width()//2 - tip.width()//2
           y = pos.y() - 5 - tip.height()

# adjust postion to prevent tooltips from appearing outside the window
           x = min(max(5, x), self.width() - tip.width() - 5)
           y = min(max(5, y), self.height() - tip.height() - 5)

tip.move(x, y)
           tip.show()
       elif e.type() == QEvent.Leave:
           tip.hide()
       elif e.type() == QEvent.ToolTip:
           return True

return super().eventFilter(obj, e)

if __name__ == '__main__':
   app = QApplication(sys.argv)
   w = Demo()
   w.show()
   app.exec_()

用到的样式文件如下:

QWidget{
   background-color: white;
}

QPushButton {
   background-color: rgb(204, 204, 204);
   padding: 10px 64px 10px 64px;
   font: 19px 'Microsoft YaHei';
   border: transparent;
   border-radius: 4px;
}

QPushButton:pressed:hover {
   background-color: rgb(153, 153, 153);
}

QPushButton:hover {
   background-color: rgb(230, 230, 230);
}

QPushButton:disabled {
   background-color: rgb(204, 204, 204);
   color: rgb(122, 122, 122);
}

后记

自定义工具提示的方法已经介绍完了,更多好康的自定义小部件参见 GitHub 仓库 https://github.com/zhiyiYo/PyQt-Fluent-Widgets

来源:https://www.cnblogs.com/zhiyiYo/p/16303940.html

标签:PyQt,自定义,工具提示,ToolTip
0
投稿

猜你喜欢

  • JS组件Bootstrap实现图片轮播效果

    2024-04-22 13:03:11
  • golang程序进度条实现示例详解

    2024-04-25 13:22:45
  • nodejs处理tcp连接的核心流程

    2024-05-03 15:55:40
  • 微信小程序开发实例详解

    2022-11-07 19:55:48
  • 不同浏览器所支持的“事件”

    2007-09-26 18:29:00
  • 浅析Python迭代器的高级用法

    2022-12-21 16:57:03
  • 解析python的局部变量和全局变量

    2023-08-23 18:17:01
  • Python遍历pandas数据方法总结

    2022-04-23 05:47:58
  • Python Matplotlib条形图之垂直条形图和水平条形图详解

    2022-07-24 04:07:45
  • php文件上传类完整实例

    2023-11-22 04:32:28
  • Python爬虫爬取Bilibili弹幕过程解析

    2021-11-26 02:58:49
  • 用ASP实现txt,doc,jpg等文件下载的函数

    2007-08-17 13:17:00
  • python3排序的实例方法

    2023-01-17 11:05:28
  • Python partial函数原理及用法解析

    2021-01-22 02:48:50
  • ASP对FoxPro自由表(DBF文件)的操作

    2010-05-27 12:20:00
  • Python3离线安装Requests模块问题

    2021-05-06 09:58:24
  • sql动态行转列的两种方法

    2024-01-24 07:17:41
  • Python数据结构之优先级队列queue用法详解

    2023-03-10 03:37:40
  • DBCC SHRINKDATABASEMS SQL数据库日志压缩方法

    2024-01-27 03:57:10
  • git_stats web代码图形统计工具详解

    2023-10-29 23:16:03
  • asp之家 网络编程 m.aspxhome.com