功能:
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_())