PySide6 自定义文本查找对话框(QFindTextDialog)以及调用示例——重构版

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())
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

开心-开心急了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值