pyqt5-文本框搜索功能

发布时间 2023-05-01 16:23:15作者: 挖洞404

1、介绍

作用是对一个文本框组件的文本进行搜索,将搜索结果在文本框中进行字体颜色标记,允许re或者普通文本搜索,支持上一个或下一个的跳转,支持标签显示当前索引和总个数。

2、ui

3、代码

(1)自定义search.py,其中包含两个重要的函数

"""
搜索算法
返回结果是list,元素是二元list,表示各搜索组的起止索引。比如[[2,15], [20,33]]
"""
import re


def search_fun(s: str, pattern: str, re_flag: bool = False):
    """search_fun(s, pattern, re_flag) -> list"""
    result = list()
    i = 0
    while i < len(s):
        if re_flag:
            r = re.search(pattern=pattern, string=s[i:])
            if r is not None:
                result.append([i + r.start(), i + r.end()])
                i = i + r.end()
            else:
                break
        else:
            if pattern in s[i:]:
                start = s.index(pattern, i)
                i = start + len(pattern)
                result.append([start, i])
            else:
                break
    return result


# print(search_fun('abcdefg', 'de', True))

"""
为搜索结果标记颜色
search_result即search_fun函数的结果
"""


def search_asAppendHtml(s: str, search_result: list, color: str = 'red'):
    """search_asAppendHtml(s, search, color) -> str"""
    last_end = 0
    result = ''
    for i in range(len(search_result)):
        s1 = s[last_end:search_result[i][0]]
        s2 = s[search_result[i][0]: search_result[i][1]]
        # pre避免连续空白符被转为单个空格字符,s1也需要包含
        result = '%s%s<span style=color:%s>%s</span>' % (result, s1, color, s2)
        # 最后一组搜索,那么其之后的字符串也需要拼接
        if i == len(search_result) - 1:
            s1 = s[search_result[i][1]:]
            result = '%s%s' % (result, s1)
    # 没有搜索结果
    if result == '':
        result = s
    # 统一的pre
    result = '<pre>%s</pre>' % result
    return result

(2)分析

有两个思路,一是必须需要按钮点击才进行搜索,而这样的话,在搜索条件变化时就必须对搜索结果清空。但这样操作相对繁琐。

二是当搜索条件发生变化时,自动触发搜索方法。需要注意的是,可能频繁触发搜索,可以考虑通过记录触发时间,当在一定时间内无新触发才直接执行,或者进行交换监视下一个触发。

暂时,优先考虑方案二。

# 搜索结果
    self.search_index_list = list()
    # 索引,显示最小为1
    self.search_index_this = 0
    self.window.pushButton: QPushButton
    self.window.pushButton.clicked.connect(self.search)
    # self.window.plainTextEdit: QPlainTextEdit
    # self.window.plainTextEdit.textChanged.connect(self.search)
    # self.window.lineEdit: QLineEdit
    # self.window.lineEdit.textChanged.connect(self.search)
    # self.window.checkBox: QCheckBox
    # self.window.checkBox.clicked.connect(self.search)
    self.window.pushButton_2: QPushButton
    self.window.pushButton_3: QPushButton
    self.window.pushButton_2.clicked.connect(self.search_pre)
    self.window.pushButton_3.clicked.connect(self.search_next)
    # 标志,为True表示可以开始搜索。为False表示此时正在搜索中,引起的事件导致搜索不执行
    self.search_flag = True

def search(self, x=None):
    if not self.search_flag:
        return
    self.search_flag = False
    self.window.plainTextEdit: QPlainTextEdit
    s = self.window.plainTextEdit.toPlainText()
    if s == '' or self.window.lineEdit.text() == '':
        self.search_flag = True
        return
    self.search_index_list = search.search_fun(s=self.window.plainTextEdit.toPlainText(),
                                               pattern=self.window.lineEdit.text(),
                                               re_flag=self.window.checkBox.isChecked())
    self.window.plainTextEdit.clear()
    self.window.plainTextEdit.appendHtml(search.search_asAppendHtml(s, self.search_index_list, 'blue'))
    # 跳转到第一个搜索结果
    self.search_index_this = 1
    self.search_turn()
    # 
    self.search_flag = True

def search_pre(self):
    self.search_index_this = self.search_index_this - 1
    if self.search_index_this == 0:
        self.search_index_this = len(self.search_index_list)

def search_next(self):
    self.search_index_this = self.search_index_this + 1
    if self.search_index_this == len(self.search_index_list):
        self.search_index_this = 0

def search_turn(self):
    # 标签标记
    self.window.label: QLabel
    # 如果没有搜索结果
    if len(self.search_index_list) == 0:
        self.window.label.setText('1/0')
        return
    self.window.label.setText('%d/%d' % (self.search_index_this, len(self.search_index_list)))
    # 跳转
    self.window.plainTextEdit: QPlainTextEdit
    t = QTextCursor()
    t.setPosition(self.search_index_list[self.search_index_this - 1][0])
    self.window.plainTextEdit.setTextCursor(t)