PySide6 自定义文本查找对话框(QFindTextDialog)以及调用示例——重构版
实现功能一览
- 向上或向下查找
- 区分大小写
- 匹配完整单词
- 循环
- 向上或向下与其他的组合
实现了 上一版 没有实现的循环
参考
代码示例
QFindTextDialog
# coding = utf-8
from PySide6.QtWidgets import (QDialog,QLabel,QLineEdit,QCheckBox,QGroupBox,QRadioButton,
QPushButton,QVBoxLayout,QHBoxLayout,QPlainTextEdit,QMessageBox)
from PySide6.QtCore import QRegularExpression
from PySide6.QtGui import QTextDocument,QTextCursor
class QFindTextDialog(QDialog):
def __init__(self,plainTextEdit: QPlainTextEdit,parent=None):
"""初始化
"""
self.plainTextEdit = plainTextEdit
super().__init__(parent)
self.setupUi()
self.setEvnetBind()
def setupUi(self):
self.setWindowTitle("查找")
self.findLabel = QLabel("查找内容(&N)") # 需要设置伙伴关系
self.findLineEdit = QLineEdit()
self.findLabel.setBuddy(self.findLineEdit)
# 全局布局 使用垂直布局
gVboxLayout = QVBoxLayout(self)
hboxLayout = QHBoxLayout()
hboxLayout.addWidget(self.findLabel)
hboxLayout.addWidget(self.findLineEdit)
# 区分大小写 与循环
self.caseSensitiveCheck = QCheckBox("区分大小写")
self.cycleCheck = QCheckBox("循环")
self.wordCheck = QCheckBox("匹配完整单词")
vboxLayout = QVBoxLayout()
vboxLayout.addWidget(self.caseSensitiveCheck)
vboxLayout.addWidget(self.cycleCheck)
vboxLayout.addWidget(self.wordCheck)
# 方向 组合盒子
self.directGroupBox = QGroupBox()
self.directGroupBox.setTitle("方向")
self.upButton = QRadioButton("向上(&U)")
self.downButton = QRadioButton("向下(&D)")
directVLayout = QVBoxLayout(self.directGroupBox)
directVLayout.addWidget(self.upButton)
directVLayout.addWidget(self.downButton)
# 默认向下
self.downButton.setChecked(True)
# 查找下一个与取消按钮
self.findNextButton = QPushButton("查找下一个(F)")
self.cancelButton = QPushButton("取消")
vboxLayout_ = QVBoxLayout()
vboxLayout_.addWidget(self.findNextButton)
vboxLayout_.addWidget(self.cancelButton)
# 添加部件与控件
gVboxLayout.addLayout(hboxLayout)
gVboxLayout.addLayout(vboxLayout)
gVboxLayout.addWidget(self.directGroupBox)
gVboxLayout.addLayout(vboxLayout_)
def setEvnetBind(self):
"""设置事件绑定
"""
# 查找下一个文本文档
self.findNextButton.clicked.connect(self.setTextCursor)
# 取消按钮触发关闭
self.cancelButton.clicked.connect(self.close)
def getRadioBtnStatus(self) -> tuple[bool,bool]:
"""获取圆角按钮状体
:return: 俩个按钮状态布尔值 的元组
"""
return (self.upButton.isChecked(),self.downButton.isChecked())
def getCheckBoxStatus(self) -> tuple[bool,bool]:
"""获取复选框的状态
:return: 表示复选框状态的元组值
"""
return (self.caseSensitiveCheck.isChecked(),self.cycleCheck.isChecked(),self.wordCheck.isChecked)
def getCycleCheckBoxStatus(self) -> bool:
"""获取循环复选框状态
:return: True|False
"""
return self.cycleCheck.isChecked()
def getFindFlags(self):
"""设置查找标签
循环未实现
后续添加完整单词
"""
# 上一个标签
prevFlags = QTextDocument.FindFlag.FindBackward
# 区分大小写标签
caseFlags= QTextDocument.FindFlag.FindCaseSensitively
# 匹配完整单词标签
wordFlags = QTextDocument.FindFlag.FindWholeWords
# 获取圆角按钮状态
upBtnStat,downBtnStat = self.getRadioBtnStatus()
# 获取复选框状态
caseSensitiveStat,cycleStat,wordStat = self.getCheckBoxStatus()
if upBtnStat:
flags = prevFlags
if caseSensitiveStat and wordStat:
flags = prevFlags | caseFlags | wordFlags
elif caseSensitiveStat:
flags = prevFlags | caseFlags
elif wordStat:
flags = prevFlags | wordFlags
elif downBtnStat:
flags = None
if caseSensitiveStat and wordStat:
flags = caseFlags | wordFlags
elif caseSensitiveStat:
flags = caseFlags
elif wordStat:
flags = wordFlags
return flags
def setTextCursor(self):
"""设置文本光标
"""
findStr = self.findLineEdit.text()
exp = QRegularExpression(findStr)
flags = self.getFindFlags()
if flags:
findRes = self.plainTextEdit.find(exp,flags)
self.isResetCursor(findRes)
else:
findRes = self.plainTextEdit.find(exp)
self.isResetCursor(findRes)
def setNoFindMsgBox(self,findResult:bool):
"""弹出找不到提示
"""
if findResult == False:
findStr = self.findLineEdit.text()
# 提示窗口
msgBox = QMessageBox(self)
msgBox.setWindowTitle("记事本") #查找窗口太小 时不会显示
msgBox.setIcon(QMessageBox.Icon.Information)
msgBox.setText(f'"{findStr}"')
msgBox.exec()
def isResetCursor(self,findResult:bool):
"""重新设置光标
"""
cycleStatus = self.getCycleCheckBoxStatus()
prevBtnStat,nextBtnStat = self.getRadioBtnStatus()
# 如果勾选 按钮为向上 从最后开始查找
# 如果勾选 按钮为向下 从开头开始查找
if cycleStatus:
if prevBtnStat and findResult == False:
self.plainTextEdit.moveCursor(QTextCursor.MoveOperation.End)
elif nextBtnStat and findResult == False:
self.plainTextEdit.moveCursor(QTextCursor.MoveOperation.Start)
else:
if findResult == False:
self.setNoFindMsgBox(findResult)
调用示例
# coding = utf-8
from PySide6.QtWidgets import QWidget,QPushButton,QVBoxLayout,QPlainTextEdit,QApplication
from findDialog import QFindTextDialog
import sys
class TestNotePad(QWidget):
def __init__(self):
super().__init__()
self.setupUi()
self.setEventBind()
def setupUi(self):
"""设置用户界面
"""
self.setWindowTitle("测试查找对话框")
# 全局使用垂直布局
vboxLayout = QVBoxLayout(self)
# 初始化 文本编辑器 按钮
self.plainTextEdit = QPlainTextEdit()
self.findPushButton = QPushButton("查找下一个")
# 将控件添加到垂直布局管理器中
vboxLayout.addWidget(self.plainTextEdit)
vboxLayout.addWidget(self.findPushButton)
def setEventBind(self):
"""设置事件绑定
"""
self.findPushButton.clicked.connect(self.getFindDialog)
def getFindDialog(self):
"""获取查找对话框
"""
findTextDialog = QFindTextDialog(self.plainTextEdit,self)
findTextDialog.show()
return findTextDialog
if __name__ == "__main__":
app = QApplication(sys.argv)
testNotePad = TestNotePad()
testNotePad.show()
sys.exit(app.exec())
1022

被折叠的 条评论
为什么被折叠?



