ZetCode

PyQt QToolTip

最后修改于 2023 年 8 月 24 日

在本文中,我们将展示如何在 PyQt 中使用工具提示 (tooltips)。

访问 Advanced PyQt5 电子书,阅读 PyQt6 教程,或列出所有 PyQt 教程

QToolTip

QToolTip 为任何组件提供工具提示(气泡帮助)。它是一段简短的文本,用于提醒用户组件的功能。工具提示可以包含富文本。

工具提示可以通过 QWidget.setToolTipQToolTip.showText 成员函数来设置。

PyQt QToolTip 示例

下面是一个使用 QToolTip 的简单示例。

simple.py
#!/usr/bin/python

import sys
from PyQt6.QtWidgets import QWidget, QToolTip, QPushButton, QApplication
from PyQt6.QtGui import QFont


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()


    def initUI(self):

        QToolTip.setFont(QFont('SansSerif', 10))

        self.setToolTip('This is a <b>QWidget</b> widget')

        btn = QPushButton('Button', self)
        btn.setToolTip('This is a <b>QPushButton</b> widget')
        btn.resize(btn.sizeHint())
        btn.move(50, 50)

        self.setGeometry(300, 300, 300, 200)
        self.setWindowTitle('Tooltips')
        self.show()


def main():

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec())


if __name__ == '__main__':
    main()

在此示例中,我们为两个 PyQt5 组件显示了工具提示。

QToolTip.setFont(QFont('SansSerif', 10))

这个静态方法设置了用于渲染工具提示的字体。我们使用 10pt 的 SansSerif 字体。

self.setToolTip('This is a <b>QWidget</b> widget')

要创建工具提示,我们调用 setTooltip 函数。我们可以使用富文本格式。

btn = QPushButton('Button', self)
btn.setToolTip('This is a <b>QPushButton</b> widget')

我们创建了一个按钮组件,并为其设置了工具提示。

QToolTip
图:QToolTip

带样式的 QToolTip

在下面的示例中,我们使用样式表来为工具提示设置样式。

styled.py
#!/usr/bin/python

import sys
from PyQt6.QtWidgets import QWidget, QToolTip, QApplication
from PyQt6.QtGui import QFont, QPalette, QColor


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):

        self.setStyleSheet('''QToolTip { 
                           background-color: #8ad4ff; 
                           color: black; 
                           border: #8ad4ff solid 1px
                           }''')

        QToolTip.setFont(QFont('Georgia', 11))

        pal = QPalette()
        pal.setColor(QPalette.ColorRole.Window, QColor('#348ceb'))
        self.setPalette(pal)

        self.setToolTip('This is QWidget')

        self.setGeometry(300, 300, 300, 200)
        self.setWindowTitle('Styled QToolTip')
        self.show()


def main():

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec())


if __name__ == '__main__':
    main()

我们使用样式表来改变工具提示的外观。此外,我们还使用 QPalette 来更改 QWidget 的背景颜色。

self.setStyleSheet('''QToolTip { 
    background-color: #8ad4ff; 
    color: black; 
    border: #8ad4ff solid 1px
    }''')

我们更改了工具提示的背景颜色、前景颜色和边框。

pal = QPalette()
pal.setColor(QPalette.ColorRole.Window, QColor('#348ceb'))
self.setPalette(pal)

我们使用 QPalette 更改了主组件的背景颜色。

Styled QToolTip
图:带样式的 QToolTip

QToolTip 鼠标位置

下面的示例在工具提示中显示鼠标位置。

mouse_positions.py
#!/usr/bin/python

import sys
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QWidget, QApplication, QGridLayout, QToolTip


class MyWidget(QWidget):

    def __init__(self):
        super().__init__()

        self.setAttribute(Qt.WidgetAttribute.WA_StyledBackground, True)
        self.setStyleSheet(
            'QWidget { background: #007AA5; border-radius: 3px;}')
        self.setMouseTracking(True)

    def mouseMoveEvent(self, e):

        self.x = e.pos().x()
        self.y = e.pos().y()

        p = self.mapToGlobal(e.pos())

        QToolTip.showText(p, f'{self.x}:{self.y}')


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):

        grid = QGridLayout()

        r = c = 0

        for _ in range(9):
            grid.addWidget(MyWidget(), r, c)

            c += 1

            if c % 3 == 0:
                c = 0
                r += 1

        self.setLayout(grid)

        self.setGeometry(400, 300, 500, 350)
        self.setWindowTitle('Mouse positions')
        self.show()


def main():

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec())


if __name__ == '__main__':
    main()

我们在主组件中放置了九个组件。当我们将光标放在其中一个组件上时,会显示一个工具提示,其中包含相对于该组件的鼠标位置。

self.setMouseTracking(True)

为了捕获鼠标移动事件,我们需要调用 setMouseTracking

def mouseMoveEvent(self, e):

    self.x = e.pos().x()
    self.y = e.pos().y()

    p = self.mapToGlobal(e.pos())

    QToolTip.showText(p, f'{self.x}:{self.y}')

在重写的 mouseMoveEvent 函数中,我们确定鼠标坐标,并使用 showText 将其显示在工具提示中。

Mouse positions
图:鼠标位置

在绘制的图形上的 QToolTip

下面的示例展示了在绘制的图形上显示工具提示。

shapes.py
#!/usr/bin/python

import sys

from PyQt6.QtCore import QEvent, QPointF, Qt
from PyQt6.QtGui import QColor, QPainter, QPainterPath, QPolygonF
from PyQt6.QtWidgets import QApplication, QToolTip, QWidget


class Shape(object):

    def __init__(self):

        self.mypath = QPainterPath()
        self.col = QColor()
        self.toottip = ''

    def path(self):
        return self.mypath

    def color(self):
        return self.col

    def toolTip(self):
        return self.toottip

    def setPath(self, path):
        self.mypath = path

    def setToolTip(self, tooltip):
        self.toottip = tooltip

    def setPosition(self, position):
        self.pos = position

    def setColor(self, color):
        self.col = color


class Example(QWidget):

    def __init__(self):
        super(Example, self).__init__()

        self.initUI()

    def initUI(self):

        self.circlePath = QPainterPath()
        self.squarePath = QPainterPath()
        self.trianglePath = QPainterPath()
        self.pentagonPath = QPainterPath()
        self.shapes = []

        self.circlePath.addEllipse(30, 50, 100, 100)
        self.squarePath.addRect(180, 50, 100, 100)

        x = self.trianglePath.currentPosition().x()
        y = self.trianglePath.currentPosition().y()

        self.trianglePath.moveTo(320, 150)
        self.trianglePath.lineTo(450, 150)
        self.trianglePath.lineTo(415, 50)
        self.trianglePath.lineTo(320, 150)

        polygon = QPolygonF()
        polygon.append(QPointF(130,  240))
        polygon.append(QPointF(100,  280))
        polygon.append(QPointF(50,   280))
        polygon.append(QPointF(20,  240))
        polygon.append(QPointF(75,  200))

        self.pentagonPath.addPolygon(polygon)

        self.createShape(self.circlePath, 'Circle', QColor('#c72602'))
        self.createShape(self.squarePath, 'Square', QColor('#32a852'))
        self.createShape(self.trianglePath, 'Triangle', QColor('#205f6e'))
        self.createShape(self.pentagonPath, 'Pentagon', QColor('#e0b107'))

        self.setWindowTitle('Shapes')
        self.resize(480, 300)
        self.show()

    def event(self, e):

        if e.type() == QEvent.Type.ToolTip:

            index = self.itemIndexAt(e.pos())

            if index != -1:
                QToolTip.showText(e.globalPos(),
                                  self.shapes[index].toolTip())
            else:
                QToolTip.hideText()
                e.ignore()

            return True

        return super(Example, self).event(e)

    def paintEvent(self, e):

        painter = QPainter(self)
        painter.setRenderHint(QPainter.RenderHint.Antialiasing)
        painter.setPen(Qt.PenStyle.NoPen)

        for shape in self.shapes:

            painter.setBrush(shape.color())
            painter.drawPath(shape.path())

    def itemIndexAt(self, pos):

        for i in range(len(self.shapes)):

            item = self.shapes[i]

            if item.path().contains(QPointF(pos)):

                return i

        return -1

    def createShape(self, path, toolTip, color):

        shape = Shape()
        shape.setPath(path)
        shape.setToolTip(toolTip)
        shape.setColor(color)

        self.shapes.append(shape)


def main():

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec())


if __name__ == '__main__':
    main()

在此示例中,我们绘制了四种图形:圆形、正方形、五边形和三角形。将鼠标悬停在每个图形上都会触发一个显示图形类型的工具提示。

def event(self, e):

    if e.type() == QEvent.Type.ToolTip:
        ...

没有专门的工具提示事件处理器。要捕获工具提示事件,我们需要重写 event 处理器,它是主事件处理器,接收所有组件的事件。

index = self.itemIndexAt(e.pos())

所有四个图形都存储在 shapes 变量中。自定义函数 itemIndexAt 用于确定我们的鼠标指针是否悬停在某个图形上。如果悬停,它会返回该图形在 shapes 集合中的索引,否则返回 -1。

if index != -1:
    QToolTip.showText(e.globalPos(),
            self.shapes[index].toolTip())
else:
    QToolTip.hideText()
    e.ignore()

return True

对于有效的索引,我们使用 showText 显示一个工具提示。如果我们在图形之外,则忽略工具提示。

return super(Example, self).event(e)

由于我们正在重写接收所有类型事件的 event 函数,我们需要将所有非工具提示的事件冒泡出去以进行处理。

def itemIndexAt(self, pos):

    for i in range(len(self.shapes)):

        item = self.shapes[i]

        if item.path().contains(QPointF(pos)):
            
            return i

    return -1

itemIndexAt 确定当前鼠标光标点下方的图形索引(如果有的话)。QPainterPathcontains 函数在给定点位于路径内部时返回 True

Shapes
图:图形

在本文中,我们学习了如何使用 PyQt 的 QToolTip

作者

我的名字是 Jan Bodnar,我是一名充满热情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。迄今为止,我已经创作了超过 1400 篇文章和 8 本电子书。我拥有超过十年的编程教学经验。

列出所有 PyQt 教程