QTextEditor多行文本块格式修改问题及解决方案咨询
问题:在QTextEditor中修改多行文本块的格式
我正在尝试在QTextEditor里修改特定多行文本块的格式,但碰到了不少麻烦:
- 用正则表达式匹配时,因为字符串里的制表符、空格不统一,有时候匹配结果返回-1,定位不到目标
- 试过用行号定位,但文本块里的换行符
\n不统一,导致错误高亮了不该改的文本块 - 核心需求是:能不能精准定位并修改多行字符串的格式?
输入原始文本
begin # Date: 8/18/2021 # Modified: t00 # User: user3 # Expiration: t00 # Justification: Keep this wildcard waiver for test # Date: 10/12/2021 # Modified: t00 # User: use1 # Expiration: t00 # Justification: testing end
预期效果
begin # Date: 8/18/2021 # Modified: t00 # User: user3 # Expiration: t00 # Justification: Keep this wildcard waiver for test *# Date: 10/12/2021 (change format) # Modified: t00 # User: use1 # Expiration: t00 # Justification: testing* end
我目前尝试的代码
def change_block_format(cls, text_editor, pattern): """ changing block format based on pattern :param input_text: string which contain all text :param pattern: string pattern which need to search :return: """ pattern = QRegExp(pattern) index = pattern.indexIn(text_editor.toPlainText()) length = pattern.matchedLength() #cursor = QTextCursor(text_editor.document()) print (pattern, index, length) for char_position in range(index, index+length, 1): cursor = QTextCursor(text_editor.document().findBlock(char_position)) cursor.movePosition(QTextCursor.EndOfLine, QTextCursor.KeepAnchor) cursor.mergeCharFormat(GuiUtil.underline_format())
解决方案思路
你的核心问题是精准匹配并选中多行文本块,然后统一修改格式。原来的代码有几个可以优化的地方:
正则表达式适配多行场景
QRegExp默认是单行模式,要匹配多行的话,需要开启QRegExp.MultilineOption和QRegExp.DotMatchesEverythingOption(让.匹配换行符)。比如你的目标块是从# Date: 10/12/2021开始到# Justification: testing结束,正则可以写成:pattern = QRegExp(r'# Date: 10/12/2021.*?# Justification: testing', QRegExp.Multiline | QRegExp.DotMatchesEverything)要是遇到空格/制表符不统一的问题,可以用
\s*代替固定空格,比如#\s*Date:来兼容各种空白字符。避免逐字符遍历,直接选中匹配的整个块
原来的代码逐字符遍历去选行,效率低还容易出错。其实拿到匹配的起始位置和长度后,可以直接用QTextCursor选中整个范围:cursor = QTextCursor(text_editor.document()) cursor.setPosition(index) cursor.setPosition(index + length, QTextCursor.KeepAnchor) # 然后直接给选中的整个块应用格式 cursor.mergeCharFormat(GuiUtil.underline_format())这样一次性选中整个目标块,不需要逐行处理,也不会因为换行符问题出错。
处理匹配失败的情况
记得加个判断,如果index == -1(匹配失败),就直接返回,避免后续报错:if index == -1: print("Pattern not found!") return
修改后的完整代码示例
def change_block_format(cls, text_editor, pattern): """ Changing block format based on pattern :param text_editor: QTextEditor instance :param pattern: string pattern which needs to be searched :return: """ # 开启多行匹配模式,让正则能跨换行匹配 regex = QRegExp(pattern, QRegExp.Multiline | QRegExp.DotMatchesEverything) full_text = text_editor.toPlainText() index = regex.indexIn(full_text) length = regex.matchedLength() if index == -1: print("Target block not found!") return # 直接选中整个匹配的文本块 cursor = QTextCursor(text_editor.document()) cursor.setPosition(index) cursor.setPosition(index + length, QTextCursor.KeepAnchor) # 应用格式(比如下划线,和你原来的逻辑一致) cursor.mergeCharFormat(GuiUtil.underline_format())
额外提示
如果你的目标块是动态的(比如不是固定日期,而是第二个# Date:开头的块),可以调整正则表达式为:
r'(?<=# Justification: .+\n)# Date: .*?# Justification: .+'
这个正则会匹配第一个# Justification:之后的那个完整块,这样不管日期是什么,都能精准定位到第二个条目。
内容的提问来源于stack exchange,提问作者user765443
相关产品推荐
相关产品推荐

