0

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

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

如果我做类似的事情

                       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;” 在文本编辑中并选择输入的文本,斜体按钮被选中。

我一直在互联网上浏览很多东西,但没有一个能像上面的代码那样帮助我实现。

在此处输入图像描述 在此处输入图像描述

4

1 回答 1

1

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

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

如果您真的想检查选择是否在任何位置包含任何格式更改,无论光标位置如何,那么您需要循环浏览选择中的所有字符并验证它们的格式。

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

使用以下代码,该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)
于 2021-12-04T03:59:12.827 回答