• 如何在 pyqt 中自定义工具提示 ToolTip


    前言

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

    实现过程

    工具提示其实就是一个带了标签的窗口,为了给工具提示加上阴影,只要给窗口设置 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,以上~~

  • 相关阅读:
    deque容器 常用 API操作
    反射在Java 中算是黑魔法的存在,你不想了解一下?
    MySQL数据库之JDBC编程
    [开源项目]可观测、易使用的SpringBoot线程池
    linux下程序分析工具总结
    软考高级系统架构设计师系列之:详细快速掌握软考高级架构设计师考试全部知识点和典型例题上篇
    基于helm的方式在k8s集群中部署gitlab - 备份恢复(二)
    图像处理ASIC设计方法 笔记5 图像卷积器硬件结构
    如何用网页绘制一个黑莓9900的键盘效果图
    利用浏览器DevTools中对React项目进行内存泄露排查
  • 原文地址:https://www.cnblogs.com/zhiyiYo/p/16303940.html