python pyqt5 3.文本编辑框弹窗查找替换,高亮显示查找的字符串

功能: 

1.点击打开查找替换按钮弹出查找替换窗口,选中字符串后打开窗口自动传值查找

2.查找到的结果全部高亮显示

3.显示查找到的结果个数,和当前查找到第几个

4.实现批量替换

效果图:

代码:

import re
import sys

from PyQt5.QtCore import QRegExp, Qt
from PyQt5.QtGui import QTextCharFormat, QColor, QTextCursor, QPalette, QFont
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QLineEdit, QLabel, QWidget, QCheckBox, \
    QStatusBar, QToolBar, QComboBox, QTextEdit


class FindReplace(QMainWindow):
    def __init__(self , parent=None):
        super(FindReplace, self).__init__(parent)

    def setupUi(self, text_edit,find_text):
        # 设置定位和左上角坐标
        self.setGeometry(1200, 200, 250, 300)
        self.setWindowTitle("查找/替换")
        self.text_edit = text_edit
        self.find_replace_window_is_open = 1
        self.find_count = 0 #查找次数

        self.find_label = QLabel("查找:")
        self.find_edit = QComboBox()
        self.find_edit.setEditable(True)
        self.find_edit.activated.connect(self.find_text)
        self.find_edit.editTextChanged.connect(self.find_text_edit)


        self.replace_label = QLabel("替换:")
        self.replace_edit = QLineEdit()

        self.find_cb_case_sensitive = QCheckBox()
        self.find_cb_case_sensitive.setChecked(True)
        #self.find_cb_case_sensitive.stateChanged.connect(self.restore_checkbox_clicked)
        self.find_label_case_sensitive = QLabel()
        self.find_label_case_sensitive.setText("不区分大小写:")

        self.find_cb_case_sensitive = QCheckBox()
        self.find_cb_case_sensitive.setChecked(True)
        #self.find_cb_case_sensitive.stateChanged.connect(self.restore_checkbox_clicked)
        self.find_label_case_sensitive = QLabel()
        self.find_label_case_sensitive.setText("全部高亮显示:")


        self.find_button = QPushButton('查找')
        self.find_button.clicked.connect(self.find_text)

        self.replace_button = QPushButton('替换')
        self.replace_button.clicked.connect(self.replace_text)
        self.replace_all_button = QPushButton('全部替换')
        self.replace_all_button.clicked.connect(self.replace_text_all)

        self.find_StatusBar1 = QToolBar()
        #self.find_StatusBar1 = QStatusBar()
        self.find_StatusBar1.setLayoutDirection(Qt.LeftToRight)
        self.find_StatusBar1_Label = QLabel()
        self.find_StatusBar1_Label.setStyleSheet("QLabel { color: blue; }")
        self.find_StatusBar1_Label.setFont(QFont("Microsoft YaHei", 8, 0))
        self.find_StatusBar1.addWidget(self.find_StatusBar1_Label)


        self.find_edit.addItem(find_text)

        layout = QVBoxLayout()
        layout.addWidget(self.find_label)
        layout.addWidget(self.find_edit)
        layout.addWidget(self.replace_label)
        layout.addWidget(self.replace_edit)
        layout.addWidget(self.find_button)
        layout.addWidget(self.replace_button)
        layout.addWidget(self.replace_all_button)
        layout.addWidget(self.find_StatusBar1)

        container = QWidget()
        container.setLayout(layout)
        self.setCentralWidget(container)

    def find_text_edit(self):
        self.position = self.text_edit.textCursor().position()
        text = self.text_edit.document().toPlainText()
        find_text = self.find_edit.currentText()
        text_edit_select = self.text_edit.textCursor().selectedText()
        if find_text == '':
            self.background_reset(text)
            return
        if text_edit_select:
            self.position = self.position - len(text_edit_select)
        self.find_and_highlight()
        if self.i > 0:
            self.find_and_select()
    def find_text(self):
        self.position = self.text_edit.textCursor().position()
        find_text = self.find_edit.currentText()
        text = self.text_edit.document().toPlainText()
        if find_text == '':
            self.background_reset(text)
            return
        self.find_and_highlight()
        if self.i > 0 :
            self.find_and_select()

    def find_and_select(self):
        text = self.text_edit.document().toPlainText()
        find_text = self.find_edit.currentText()
        re_search = QRegExp(find_text)
        matches = re.finditer(re_search.pattern(), text)
        length = len(find_text)
        format = QTextCharFormat()
        format.setBackground(QColor("yellow"))
        # 循环查找文档
        j = 0
        for match in matches:
            if j == 0:
                self.start_match = match
            j += 1
            index = match.start()
            if index >= self.position:
                cursor = self.text_edit.textCursor()
                cursor.setPosition(index)
                cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, length)
                #self.text_edit.setFocus()
                self.text_edit.setTextCursor(cursor)
                cursor = self.text_edit.textCursor()
                cursor.mergeCharFormat(format)  # 改变文本的背景颜色
                self.find_StatusBar1_Label.setText(str(self.i) + '个结果,当前第' + str(j) + '个')
                break
            #判断如果到最后则显示第一个
            if self.i > 0 and self.i == j:
                index = self.start_match.start()
                cursor = self.text_edit.textCursor()
                cursor.setPosition(index)
                cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, length)
                # self.text_edit.setFocus()
                self.text_edit.setTextCursor(cursor)
                cursor = self.text_edit.textCursor()
                cursor.mergeCharFormat(format)  # 改变文本的背景颜色
                self.find_StatusBar1_Label.setText(str(self.i) + '个结果,当前第1个')


    def find_and_highlight(self):
        text_edit_select = self.text_edit.textCursor().selectedText()
        text = self.text_edit.document().toPlainText()
        find_text = self.find_edit.currentText()
        re_search = QRegExp(find_text)
        matches = re.finditer(re_search.pattern(), text)
        length = len(find_text)

        # 设置背景颜色为白色
        self.background_reset(text)

        cursor = self.text_edit.textCursor()
        format = QTextCharFormat()
        format.setBackground(QColor("yellow"))

        self.i = 0
        # 循环查找文档对该值进行选中显示
        for match in re.finditer(re.escape(find_text), text):
            self.i += 1
            start = match.start()
            end = match.end()
            cursor.setPosition(start)
            cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, end - start)
            cursor.mergeCharFormat(format)
        self.find_edit.setStyleSheet("QComboBox { color: black; }")
        self.find_StatusBar1_Label.setText(str(self.i) + '个结果')
        if self.i == 0:
            self.find_edit.setStyleSheet("QComboBox { color: red; }")
            self.find_StatusBar1_Label.setStyleSheet("QLabel { color: red; }")
        else:
            self.find_StatusBar1_Label.setStyleSheet("QLabel { color: blue; }")
        #判断第一次进入如果textedit选中字符串等于查找字符串,则将光标移动到初始化为止-查找字符串长度,方便查找第一次被选中
        if self.find_count == 0 and text_edit_select == find_text:
            self.position = self.position - len(find_text)
        self.find_count += 1



    def replace_text(self):
        text = self.text_edit.document().toPlainText()
        find_text = self.find_edit.currentText()
        replace_text = self.replace_edit.text()

        self.background_reset(text)
        if find_text:
            text = text.replace(find_text, replace_text)
            self.text_edit.setPlainText(text)
    def replace_text_all(self):
        text_edit_select = self.text_edit.textCursor().selectedText()
        text = self.text_edit.document().toPlainText()
        find_text = self.find_edit.currentText()
        replace_text = self.replace_edit.text()
        self.background_reset(text)
        if find_text == text_edit_select:
            text = text.replace(find_text, replace_text)
            self.text_edit.setPlainText(text)

    def background_reset(self,text):
        # 设置背景颜色为白色
        format = QTextCharFormat()
        format.setBackground(QColor("white"))
        cursor = self.text_edit.textCursor()
        cursor.setPosition(0)
        cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, len(text))
        cursor.mergeCharFormat(format)  # 改变文本的背景颜色

    def closeEvent(self, event):
        # 在这里添加你想要在关闭窗口时执行的操作
        self.background_reset(self.text_edit.document().toPlainText())
        self.find_replace_window_is_open = 0
        # 设置背景颜色为白色
        text = self.text_edit.document().toPlainText()
        self.background_reset(text)
        print("窗口关闭")
        event.accept()

class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setWindowTitle("主窗口")
        self.setGeometry(400, 100, 1100, 800)
        self.text_edit = QTextEdit()


        self.button = QPushButton("打开查找替换窗口")
        self.button.clicked.connect(self.open_find_replace_window)

        layout = QVBoxLayout()
        layout.addWidget(self.text_edit)
        layout.addWidget(self.button)

        container = QWidget()
        container.setLayout(layout)
        self.setCentralWidget(container)

    def open_find_replace_window(self):
        find_text = self.text_edit.textCursor().selectedText()
        self.find_replace_window = FindReplace(self)
        self.find_replace_window.setupUi(self.text_edit,find_text)
        self.find_replace_window.show()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值