有没有办法用 QTextEdit 或在 QTextEdit 中绘制控制字符,类似于 Sublime Text 3 和 Notepad++ 的方式。
控制字符显示示例
我不确定他们使用的字体是否包含这些控制字符,或者他们是否正在绘制一个带有文本的矩形来代替这些字符。
几周前我遇到了一个稍微不同的问题,我不得不创建一个带有 QCompleter 的 QLineEdit 和一个显示当前匹配的视图。 .
最简单的解决方案是使用 QStyledItemDelegate。那里有一个自定义 QFontMetric,它包含有关 Textstyle 的信息。您只需使用给定的样式信息在给定的坐标处绘制文本。
我认为没有像 Sublime Text 3 那样“正确”地绘制它的方法,但是使用 QFont、QFontMetrics 和正确的 QRectF 是一个好的开始。
一些有用的链接:
子类 QStyleItemDelegate 类的示例绘制函数:
def paint(self, painter: QPainter, option: 'QStyleOptionViewItem', index: QModelIndex) -> None:
"""
paint the text
:param painter: painter to draw
:param option: style options
:param index: index with data
:return: None
"""
if not index.isValid():
super(CompleterItemDelegate, self).paint(painter, option, index)
return
# self.initStyleOption(option, index) # we do not init the options because this draws the text
painter.setFont(QApplication.font())
# draw correct background
style: QStyle = option.widget.style() if option.widget else QApplication.style()
style.drawControl(QStyle.CE_ItemViewItem, option, painter, option.widget)
# get current string
txt = str(index.data(Qt.DisplayRole))
if len(txt) == 0 or len(self._search) == 0:
painter.drawText(option.rect, Qt.AlignVCenter, txt)
painter.restore()
return
equal: int = 0
for j in range(len(self._search)):
c_s = self._search[j]
for i in range(len(txt)):
c = txt.lower()[i]
if c == c_s and i == j:
equal += 1
if self._color is None:
self._color = option.palette.color(QPalette.ColorGroup.Active, QPalette.ColorRole.HighlightedText)
# calculate and draw the selected text
left_text = txt[:equal]
right_text = txt[equal:]
w1 = option.fontMetrics.horizontalAdvance(left_text)
w2 = option.fontMetrics.horizontalAdvance(right_text)
rect = option.rect
h = option.fontMetrics.height()
margins = option.widget.contentsMargins()
p1 = rect.topLeft() + QPointF(margins.left(), (rect.height() - h) / 2)
p2 = p1 + QPointF(w1, 0)
rect1 = QRectF(p1, QSizeF(w1, h))
rect2 = QRectF(p2, QSizeF(w2, h))
painter.setPen(self._color)
painter.drawText(rect1, left_text)
painter.setPen(option.palette.color(QPalette.Text))
painter.drawText(rect2, Qt.AlignVCenter, txt[equal:])