PySide6实现高效文本查找功能
PySide6 文本编辑器实现查找功能(重构版本)
核心思路
通过继承 QPlainTextEdit 并添加查找对话框实现功能,采用 MVC 模式分离逻辑与界面,支持以下特性:
- 区分大小写查找
- 整词匹配
- 正则表达式搜索
- 搜索结果高亮显示
实现步骤
1. 创建基础编辑器类
from PySide6.QtWidgets import QPlainTextEdit, QWidget, QVBoxLayout, QDialog, QLabel, QLineEdit
from PySide6.QtCore import Qt, QRegularExpression
from PySide6.QtGui import QTextCursor, QTextCharFormat, QColor
class CodeEditor(QPlainTextEdit):
def __init__(self, parent=None):
super().__init__(parent)
self.search_format = QTextCharFormat()
self.search_format.setBackground(QColor("yellow"))
2. 实现查找核心逻辑
def find_text(self, search_str, case_sensitive=False, whole_words=False, regex=False):
cursor = self.textCursor()
flags = QTextDocument.FindFlag(0)
if case_sensitive:
flags |= QTextDocument.FindCaseSensitively
if whole_words:
flags |= QTextDocument.FindWholeWords
if regex:
regex = QRegularExpression(search_str)
if not regex.isValid():
return False
cursor = self.document().find(regex, cursor)
else:
cursor = self.document().find(search_str, cursor, flags)
if not cursor.isNull():
self.setTextCursor(cursor)
self.highlight_match(cursor)
return True
return False
def highlight_match(self, cursor):
extra_selections = []
selection = QTextEdit.ExtraSelection()
selection.format = self.search_format
selection.cursor = cursor
extra_selections.append(selection)
self.setExtraSelections(extra_selections)
3. 创建查找对话框
class FindDialog(QDialog):
def __init__(self, editor, parent=None):
super().__init__(parent)
self.editor = editor
self.setWindowTitle("查找")
layout = QVBoxLayout()
self.search_input = QLineEdit()
layout.addWidget(QLabel("查找内容:"))
layout.addWidget(self.search_input)
self.setLayout(layout)
self.search_input.returnPressed.connect(self.find_next)
def find_next(self):
search_text = self.search_input.text()
if search_text:
self.editor.find_text(search_text)
4. 集成到主窗口
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.editor = CodeEditor()
self.find_dialog = FindDialog(self.editor)
layout = QVBoxLayout()
layout.addWidget(self.editor)
self.setLayout(layout)
重构改进点
1. 职责分离
- 将查找逻辑完全封装在
CodeEditor类中 - 对话框仅负责用户输入传递
2. 性能优化
- 使用
QRegularExpression替代原生字符串匹配 - 通过
ExtraSelection实现高性能高亮
3. 可扩展性
- 预留接口支持替换高亮样式
- 对话框设计支持未来添加更多搜索选项
高级功能扩展方向
1. 批量高亮所有匹配项
def highlight_all_matches(self, search_str):
cursor = QTextCursor(self.document())
while True:
cursor = self.document().find(search_str, cursor)
if cursor.isNull():
break
self.highlight_match(cursor)
2. 添加替换功能
def replace_text(self, search_str, replace_str):
cursor = self.textCursor()
if cursor.hasSelection() and cursor.selectedText() == search_str:
cursor.insertText(replace_str)
最佳实践建议
- 对长文档搜索使用后台线程
- 限制高频搜索操作的执行间隔
- 添加搜索历史记录功能
- 实现撤销/重做支持
这种实现方式既保持了代码的清晰结构,又为功能扩展留下充足空间,适合作为中等规模文本编辑器的核心查找模块。
BbS.okapop051.sbs/PoSt/1122_462556.HtM
BbS.okapop052.sbs/PoSt/1122_852300.HtM
BbS.okapop053.sbs/PoSt/1122_943135.HtM
BbS.okapop054.sbs/PoSt/1122_109703.HtM
BbS.okapop055.sbs/PoSt/1122_936758.HtM
BbS.okapop056.sbs/PoSt/1122_707066.HtM
BbS.okapop057.sbs/PoSt/1122_775335.HtM
BbS.okapop058.sbs/PoSt/1122_041063.HtM
BbS.okapop059.sbs/PoSt/1122_723809.HtM
BbS.okapop060.sbs/PoSt/1122_693941.HtM
BbS.okapop051.sbs/PoSt/1122_943996.HtM
BbS.okapop052.sbs/PoSt/1122_911750.HtM
BbS.okapop053.sbs/PoSt/1122_494527.HtM
BbS.okapop054.sbs/PoSt/1122_260420.HtM
BbS.okapop055.sbs/PoSt/1122_042935.HtM
BbS.okapop056.sbs/PoSt/1122_139003.HtM
BbS.okapop057.sbs/PoSt/1122_696665.HtM
BbS.okapop058.sbs/PoSt/1122_239841.HtM
BbS.okapop059.sbs/PoSt/1122_278390.HtM
BbS.okapop060.sbs/PoSt/1122_607704.HtM
BbS.okapop051.sbs/PoSt/1122_484455.HtM
BbS.okapop052.sbs/PoSt/1122_920259.HtM
BbS.okapop053.sbs/PoSt/1122_306877.HtM
BbS.okapop054.sbs/PoSt/1122_052598.HtM
BbS.okapop055.sbs/PoSt/1122_883477.HtM
BbS.okapop056.sbs/PoSt/1122_911142.HtM
BbS.okapop057.sbs/PoSt/1122_027137.HtM
BbS.okapop058.sbs/PoSt/1122_186176.HtM
BbS.okapop059.sbs/PoSt/1122_583437.HtM
BbS.okapop060.sbs/PoSt/1122_157328.HtM
BbS.okapop051.sbs/PoSt/1122_168293.HtM
BbS.okapop052.sbs/PoSt/1122_855118.HtM
BbS.okapop053.sbs/PoSt/1122_411355.HtM
BbS.okapop054.sbs/PoSt/1122_873070.HtM
BbS.okapop055.sbs/PoSt/1122_808212.HtM
BbS.okapop056.sbs/PoSt/1122_427555.HtM
BbS.okapop057.sbs/PoSt/1122_830144.HtM
BbS.okapop058.sbs/PoSt/1122_517299.HtM
BbS.okapop059.sbs/PoSt/1122_870118.HtM
BbS.okapop060.sbs/PoSt/1122_671087.HtM
BbS.okapop061.sbs/PoSt/1122_510642.HtM
BbS.okapop062.sbs/PoSt/1122_941742.HtM
BbS.okapop063.sbs/PoSt/1122_721828.HtM
BbS.okapop065.sbs/PoSt/1122_067694.HtM
BbS.okapop066.sbs/PoSt/1122_635540.HtM
BbS.okapop067.sbs/PoSt/1122_303223.HtM
BbS.okapop068.sbs/PoSt/1122_057362.HtM
BbS.okapop069.sbs/PoSt/1122_482982.HtM
BbS.okapop070.sbs/PoSt/1122_226373.HtM
BbS.okapop071.sbs/PoSt/1122_710204.HtM
BbS.okapop061.sbs/PoSt/1122_833518.HtM
BbS.okapop062.sbs/PoSt/1122_453399.HtM
BbS.okapop063.sbs/PoSt/1122_332766.HtM
BbS.okapop065.sbs/PoSt/1122_538563.HtM
BbS.okapop066.sbs/PoSt/1122_954638.HtM
BbS.okapop067.sbs/PoSt/1122_291193.HtM
BbS.okapop068.sbs/PoSt/1122_254863.HtM
BbS.okapop069.sbs/PoSt/1122_785520.HtM
BbS.okapop070.sbs/PoSt/1122_875544.HtM
BbS.okapop071.sbs/PoSt/1122_765058.HtM
BbS.okapop061.sbs/PoSt/1122_484713.HtM
BbS.okapop062.sbs/PoSt/1122_802266.HtM
BbS.okapop063.sbs/PoSt/1122_940969.HtM
BbS.okapop065.sbs/PoSt/1122_367247.HtM
BbS.okapop066.sbs/PoSt/1122_203453.HtM
BbS.okapop067.sbs/PoSt/1122_604822.HtM
BbS.okapop068.sbs/PoSt/1122_711278.HtM
BbS.okapop069.sbs/PoSt/1122_432184.HtM
BbS.okapop070.sbs/PoSt/1122_820521.HtM
BbS.okapop071.sbs/PoSt/1122_038914.HtM
BbS.okapop061.sbs/PoSt/1122_659835.HtM
BbS.okapop062.sbs/PoSt/1122_333647.HtM
BbS.okapop063.sbs/PoSt/1122_542140.HtM
BbS.okapop065.sbs/PoSt/1122_744304.HtM
BbS.okapop066.sbs/PoSt/1122_485547.HtM
BbS.okapop067.sbs/PoSt/1122_632190.HtM
BbS.okapop068.sbs/PoSt/1122_588604.HtM
BbS.okapop069.sbs/PoSt/1122_559760.HtM
BbS.okapop070.sbs/PoSt/1122_635323.HtM
BbS.okapop071.sbs/PoSt/1122_572019.HtM


