检查 QTextEdit 中所选文本的格式 - PySide6

Checking formatting of selected text in QTextEdit - PySide6

我正在开发一个富文本编辑器,遇到了一个小问题,我用看起来像是“hack”的方式解决了这个问题。

所以我想检查所选文本或光标位置的文本是否有任何格式、粗体、斜体等,并检查执行相应工作的相应按钮,但它变得很奇怪。

如果我做类似的事情

                       if self.ed.fontItalic() is True:
                            self.italic.setChecked(True)
                        else:
                            self.italic.setChecked(False)
            
                        if self.ed.fontUnderline() is True:
                            self.uline.setChecked(True)
                        else:
                            self.uline.setChecked(False)

其中“self.italic”和“self.uline”是可检查的 QPushButtons;

只检查光标下的格式,而不检查斜体和下划线的两个按钮,即,如果所选文本具有机器人格式。

基本上,它会忽略所选文本并查找光标下文本的格式。

所以我目前正在解析 html 以查看它是否具有格式;

   def check_formatting(self):

        if self.ed.textCursor().hasSelection():
            print(self.ed.textCursor().selection().toHtml())
            if "font-style:italic;" in self.ed.textCursor().selection().toHtml():
                self.italic.setChecked(True)
            else:
                self.italic.setChecked(False)

            if "text-decoration: underline;" in self.ed.textCursor().selection().toHtml():
                self.uline.setChecked(True)
            else:
                self.uline.setChecked(False)

        else:
            if self.ed.fontItalic() is True:
                self.italic.setChecked(True)
            else:
                self.italic.setChecked(False)

            if self.ed.fontUnderline() is True:
                self.uline.setChecked(True)
            else:
                self.uline.setChecked(False)

点击按钮时设置选中文本或光标下文本格式的代码如下

    def set_italic(self):
                if self.italic.isChecked():
                    self.ed.setFontItalic(True)
                    if self.ed.textCursor().hasSelection():
                        if self.ed.fontItalic() != QTextFormat.FontItalic:
                            self.ed.setFontItalic(True)
                        else:
                            self.ed.setFontItalic(False)
                else:
                    self.ed.setFontItalic(False)

所有这一切都几乎按预期工作,但感觉超级 hacky。通过 html 解析,显然,如果用户输入“font-style:italic;”在文本编辑中选择输入的文本,选中斜体按钮。

我一直在 Internet 上浏览很多资料,但其中 none 对我的帮助与上述代码一样多。

默认行为是预期的,从编程的角度来看,不可能知道开发人员是否有兴趣知道选择是否在 any 点设置了格式,或者他们想知道它是否 包含该格式。

此外,检查文档的 html 在概念上是错误的,因为可以在选择之外设置格式(包括默认样式表的使用),并且记住 toHtml() 函数 returns 底层 QTextDocument 的“翻译”,它不是文档对象本身。
验证指定位置格式的唯一正确方法是获取给定字符位置的文本光标的 QTextCharFormat

如果您真的想检查所选内容是否在任何位置包含任何格式更改,无论光标位置如何,则需要循环遍历所选内容中的所有字符并验证其格式。

请注意,在这种情况下,您需要连接到 cursorPositionChangedselectionChanged 信号,因为用户可以单击光标处的编辑器位置,这将清除选择但不会更改光标位置。

使用下面的代码,check_formatting函数会自动切换按钮,这样你就不需要在按钮函数中检查当前格式,而是可以直接连接到文本编辑函数作为他们将完全根据 check_formatting 设置的状态切换格式,从而覆盖默认行为。

class Editor(QtWidgets.QWidget):
    def __init__(self):
        # ...
        self.ed.cursorPositionChanged.connect(self.check_formatting)
        self.ed.selectionChanged.connect(self.check_formatting)

        self.bold.toggled.connect(self.toggle_bold)
        self.italic.toggled.connect(self.ed.setFontItalic)
        self.underline.toggled.connect(self.ed.setFontUnderline)

    def toggle_bold(self, bold):
        self.ed.setFontWeight(QtGui.QFont.Bold if bold else QtGui.QFont.Normal)

    def check_formatting(self):
        # assume no format by default
        bold = italic = underline = False
        cursor = self.ed.textCursor()
        if cursor.hasSelection():
            rangeEnd = cursor.selectionEnd() + 1
        else:
            rangeEnd = cursor.selectionStart() + 1
        for pos in range(cursor.selectionStart(), rangeEnd):
            cursor.setPosition(pos)
            fmt = cursor.charFormat()
            if fmt.fontWeight() >= QtGui.QFont.Bold:
                bold = True
            if fmt.fontItalic():
                italic = True
            if fmt.fontUnderline():
                underline = True
            if all((bold, italic, underline)):
                # all formats are set, no need for further checking
                break

        # set check states of buttons but block their signals to avoid
        # unnecessary calls and unwanted behavior when using keyboard
        # navigation for selection (eg: shift+arrows)
        with QtCore.QSignalBlocker(self.bold):
            self.bold.setChecked(bold)
        with QtCore.QSignalBlocker(self.italic):
            self.italic.setChecked(italic)
        with QtCore.QSignalBlocker(self.underline):
            self.underline.setChecked(underline)