如何在 QTextEdit 中绘制控制字符?

问题描述 投票:0回答:1

有没有办法用 QTextEdit 或在 QTextEdit 中绘制控制字符,类似于 Sublime Text 3 和 Notepad++ 的方式。

控制字符显示示例

我不确定他们使用的字体是否包含这些控制字符,或者他们是否正在绘制一个带有文本的矩形来代替这些字符。

qt qtextedit control-characters
1个回答
0
投票

几周前我遇到了一个稍微不同的问题,我不得不创建一个带有 QCompleter 的 QLineEdit 和一个显示当前匹配的视图。 Example QLineEdit with QListView and QStyledItemDelegate.

最简单的解决方案是使用 QStyledItemDelegate。那里有一个自定义 QFontMetric,它包含有关 Textstyle 的信息。您只需使用给定的样式信息在给定的坐标处绘制文本。

我认为没有像 Sublime Text 3 那样“正确”地绘制它的方法,但是使用 QFont、QFontMetrics 和正确的 QRectF 是一个好的开始。

一些有用的链接:

获取每个字符的边界框

QStyledItemDelegate 示例

子类 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:])
© www.soinside.com 2019 - 2024. All rights reserved.