Contents

原创作品,允许转载。转载时请务必以超链接形式标明文章原始出处、作者信息和本声明,否则将追究法律责任。

在日常开发中,我们经常会用到QtTooltips,但是默认的样式不够美观,而且不支持富文本,于是一般情况都会重写Tooltips

以下是我的实现,用了QSS样式表,所以不需要任何美术资源。阴影部分也是用QtGui.QPainter绘制的,可调节XY偏移值。富文本显示使用html标签,所以换行需要手动输入<br>Tooltips会自动适应大小。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import math
from PyQt4 import QtCore, QtGui
class Tooltips(QtGui.QMainWindow):
TOOLTIPS_LINE_HEIGHT = 18
def __init__(self, parent):
super(Tooltips, self).__init__(parent)
self.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.FramelessWindowHint)
self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
self.setAttribute(QtCore.Qt.WA_DontCreateNativeAncestors)
self.setAttribute(QtCore.Qt.WA_ShowWithoutActivating)
self.hide()
self.setStyleSheet('Tooltips > QLabel {border: 1px solid #f56133; border-radius: 4px; background: #ffffff; font: normal 12px 'Microsoft Yahei'; padding: 8px;}')
self._actualWidth = 150
self._actualHeight = 50
self._offsetXShadow = 5
self._offsetYShadow = 5
self._labelText = QtGui.QLabel(self)
self._labelText.setWordWrap(True)
self._labelText.move(0, 0)
self._labelText.setText(u'')
self._labelText.setAlignment(QtCore.Qt.AlignVCenter)
def setText(self, str_text):
self._labelText.setText(str_text)
self.adjustSize()
def text(self):
return self._labelText.text()
def resize(self, *__args):
if len(__args) == 1:
if not isinstance(__args[0], QtCore.QSize):
return
self._actualWidth = __args[0].width()
self._actualHeight = __args[0].height()
super(Tooltips, self).resize(__args[0] + QtCore.QSize(self._offsetXShadow, self._offsetYShadow))
elif len(__args) == 2:
if not isinstance(self._actualWidth, int):
return
if not isinstance(self._actualHeight, int):
return
self._actualWidth = __args[0]
self._actualHeight = __args[1]
super(Tooltips, self).resize(self._actualWidth + self._offsetXShadow,
self._actualHeight + self._offsetYShadow)
def resizeEvent(self, event):
self._labelText.resize(event.size() - QtCore.QSize(self._offsetXShadow, self._offsetYShadow))
def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing, True)
color = QtGui.QColor(0, 0, 0, 0)
for i in range(0, 10):
path = QtGui.QPainterPath()
path.setFillRule(QtCore.Qt.WindingFill)
path.addRect(10 - i, 10 - i, super(Tooltips, self).width() - (10 - i) * 2,
super(Tooltips, self).height() - (10 - i) * 2)
color.setAlpha(150 - math.sqrt(i) * 50)
painter.setPen(color)
painter.drawPath(path)
def width(self):
return self._actualWidth
def height(self):
return self._actualHeight
def size(self):
return QtCore.QSize(self._actualWidth, self._actualHeight)
def adjustSize(self):
orgText = self.text()
countLF = orgText.count('<br>') + 1
plainText = orgText.replace('<br>', '\n').replace(QtCore.QRegExp('<[^>]+>'), '').replace(' ', ' ')
tgtWidth = self._maxLineWidth(plainText)
tgtRect = QtCore.QSize(tgtWidth, Tooltips.TOOLTIPS_LINE_HEIGHT * countLF + 19)
if self.width() != tgtRect.width() or self.height() != tgtRect.height():
self.resize(tgtRect)
def _maxLineWidth(self, text):
maxLineWidth = 0
for line in text.split('\n'):
if line == '':
continue
tmpWidth = self._labelText.fontMetrics().width(line) + 24
if tmpWidth > maxLineWidth:
maxLineWidth = tmpWidth
return maxLineWidth
def setShadowOffset(self, int_offsetX, int_offsetY):
self._offsetXShadow = int_offsetX
self._offsetYShadow = int_offsetY
self.resize(self._actualWidth, self._actualHeight)
Contents