因为本质上都是QT,所以我标题带了QT,这个思路是没问题的,就是用C++得换个语言。
最开始想根据之前一篇博客的思路进行高亮
PyQT/PySide 文本浏览器跳转到指定行,并高亮指定行_qt 指定行高亮_Toblerone_Wind的博客-CSDN博客https://blog.csdn.net/qq_42276781/article/details/127093403突然想到,QT中的文本浏览器可以设置成HTML的富文本格式,可以解析HTML语法,从而实现关键词高亮。例如,在HTML中,如果想让一个词apple变成红色,只需将原文本由apple替换为
<font color="red">apple</font>
或
<div style="color:red">apple</div>
这里在文本格式化类中实现了一个高亮函数,来高亮指定的关键词
import html
import re
class TextFormatter():
__replacement = r'<font color="red">\1</font>' # 替换后保留原单词的大小写
__keywords = ['TODO','FIXME','HACK','XXX','WORKAROUND']
def highlight_keywords(self, text:str) -> str:
# 转义特定字符,防止HTML误解析
text = html.escape(text)
for keyword in self.__keywords:
# 匹配时不考虑大小写,如需考虑移除re.IGNORECASE即可
pattern = re.compile(f'({re.escape(keyword)})', re.IGNORECASE)
text = pattern.sub(self.__replacement, text)
return text.strip()
在highlight_keywords
函数内部,我们首先使用 html.escape
对文本进行转义,以确保字符的兼容性。然后,针对每个关键词,我们使用正则表达式进行替换操作,将匹配到的关键词用 <font color="red">关键词</font>
标签包裹起来以实现高亮效果。
使用正则表达式模式 re.compile(f'({re.escape(keyword)})', re.IGNORECASE)
来匹配指定单词,并且在替换时通过\1
保留原单词的大小写。
re.escape(keyword)
用于转义特殊字符,re.IGNORECASE
参数用于忽略大小写。然后,使用 pattern.sub(self.__replacement, text)
进行替换操作,将匹配到的关键词替换为 <font color="red">
关键词</font>
。
完整代码
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
from sys import argv
import html
import re
class TextFormatter():
__replacement = r'<font color="red">\1</font>' # 替换后保留原单词的大小写
__keywords = ['TODO','FIXME','HACK','XXX','WORKAROUND']
def highlight_keywords(self, text:str) -> str:
# 转义特定字符,防止HTML误解析
text = html.escape(text)
for keyword in self.__keywords:
# 匹配时不考虑大小写,如需考虑移除re.IGNORECASE即可
pattern = re.compile(f'({re.escape(keyword)})', re.IGNORECASE)
text = pattern.sub(self.__replacement, text)
return text.strip()
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
if not MainWindow.objectName():
MainWindow.setObjectName(u"MainWindow")
MainWindow.resize(300, 250)
self.centralwidget = QWidget(MainWindow)
self.centralwidget.setObjectName(u"centralwidget")
self.formLayout = QFormLayout(self.centralwidget)
self.formLayout.setObjectName(u"formLayout")
self.textBrowser = QTextBrowser(self.centralwidget)
self.textBrowser.setObjectName(u"textBrowser")
self.textBrowser.setLineWrapMode(QTextEdit.NoWrap)
self.textBrowser.setReadOnly(False)
font = QFont()
font.setFamily(u"Arial")
font.setPointSize(22)
self.textBrowser.setFont(font)
self.textBrowser.setHtml(u"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:'Consolas'; font-size:20pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p></body></html>")
self.formLayout.setWidget(0, QFormLayout.SpanningRole, self.textBrowser)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QMetaObject.connectSlotsByName(MainWindow)
# setupUi
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
text = 'TODO is a food todo' # 文本
text = TextFormatter().highlight_keywords(text) # 高亮关键词
self.textBrowser.setText(text) # 导入textBrowser
# retranslateUi
if __name__ == "__main__":
app = QApplication(argv) # 创建应用程序
mainWindow = QMainWindow() # 创建窗口
ui = Ui_MainWindow()
ui.setupUi(mainWindow)
mainWindow.show() # 显示窗口
exit(app.exec_()) # 运行程序直到关闭
效果,文本是TODO is a food todo,高亮显示时不改变原单词的大小写