第六章(下) 搜索、查找、替换等功能实现

在这一部分我们会实现搜索功能,自定义查找对话框 用于查找。

6.4 搜索功能

PySide6对于访问常见的桌面服务的方法,有一个专门的类QDesktopServices,我们借助提供的openUrl方法就可以让其访问某个网页链接(如:www.baidu.com)。

学习过网络爬虫的读者可能会有所了解,搜索引擎其实就是一个具有参数的网址,当我们传入搜索词的时候 其实就实现了搜索功能

注意搜索引擎相关

6.4.1实现思路

实现思路 bing_search方法:

  1. 选中并获取选中文本内容
  2. 将选中文本内容传入https://cn.bing.com/search?q=%s%s
  3. 使用QDesktopServices.openUrl(f"https://cn.bing.com/search?q={select_text}")访问

重点

  1. 获取文本:QPlainTextEdit.textCursor().selectedText()
  2. 使用Bing搜索按钮是否可用setEnabled()能否复制copyAvailable信号连接

注意使用Bing搜索 按钮是否可用,其实是看是否有文本选中, 能否复制copyAvailable就是这个逻辑

6.4.2 实现代码

custom_menu.py

from PySide6.QtWidgets import QMenu,QPlainTextEdit
from PySide6.QtGui import QKeySequence,QGuiApplication,QDesktopServices

class FileMenu(QMenu):
    """文件菜单

    :param QMenu: PySide6 菜单类
    """
    pass

class EditMenu(QMenu):
    """编辑菜单

    :param QMenu: PySide6 菜单类
    """
    def __init__(self):
        """初始化
        """
        super().__init__()
        self.setup_ui()
    
    def setup_ui(self):
        """设置菜单项
        """
        self.setTitle("编辑(&E)",)
        self.undo = self.addAction("撤销(&U)",QKeySequence.StandardKey.Undo)
        self.addSeparator()
        self.cut =  self.addAction("剪切(&T)",QKeySequence.StandardKey.Cut)
        self.copy = self.addAction("复制(&C)",QKeySequence.StandardKey.Copy)
        self.paste = self.addAction("粘贴(&P)",QKeySequence.StandardKey.Paste)
        self.delete = self.addAction("删除(&L)",QKeySequence.StandardKey.Delete)
        self.addSeparator()
        self.search =  self.addAction("使用Bing搜索")
        find_ = self.addAction("查找(&F)",QKeySequence.StandardKey.Find)
        find_next = self.addAction("查找下一个(&N)",QKeySequence.StandardKey.FindNext)
        find_previous =  self.addAction("查找上一个(&V)",QKeySequence.StandardKey.FindPrevious)
        replace =  self.addAction("替换(&R)",QKeySequence.StandardKey.Replace)
        goto =self.addAction("转到(&G)","Ctrl+G")
        self.addSeparator()
        self.select_all = self.addAction("全选(&A)",QKeySequence.StandardKey.SelectAll)
        date_ = self.addAction("时间/日期(&D)","F5")

        # 默认状态  撤销、剪切、复制、粘贴、删除 、搜索不可用
        self.undo.setEnabled(False)
        self.cut.setEnabled(False)
        self.copy.setEnabled(False)
        self.paste.setEnabled(False)
        self.delete.setEnabled(False)
        self.search.setEnabled(False)

        # 初始化剪贴板
        self.clipbaord_ = QGuiApplication.clipboard()

    def set_event_bind(self,plain_text_edit:QPlainTextEdit):
        """设置必应搜索

        :param plain_text_edit: PySide6 QPlainTextEdit
        """
        # 设置状态 撤销、剪切、复制、粘贴、删除、搜索
        plain_text_edit.undoAvailable.connect(self.undo.setEnabled)
        plain_text_edit.copyAvailable.connect(self.cut.setEnabled)
        plain_text_edit.copyAvailable.connect(self.copy.setEnabled)
        self.clipbaord_.dataChanged.connect(self.reset_paste_state)
        plain_text_edit.copyAvailable.connect(self.delete.setEnabled)
        plain_text_edit.copyAvailable.connect(self.search.setEnabled)

        # 撤销、剪切、复制、粘贴、删除 、全选  搜索行为的绑定
        self.undo.triggered.connect(plain_text_edit.undo)
        self.cut.triggered.connect(plain_text_edit.cut)
        self.copy.triggered.connect(plain_text_edit.copy)
        self.paste.triggered.connect(plain_text_edit.paste)
        self.delete.triggered.connect(plain_text_edit.clear)
        self.select_all.triggered.connect(plain_text_edit.selectAll)
        self.search.triggered.connect(lambda: self.bing_search(plain_text_edit))

    def reset_paste_state(self):
        """重新设置粘贴状态
        """
        clipbaord_text = self.clipbaord_.text()
        if clipbaord_text:
            self.paste.setEnabled(True)
        else:
            self.paste.setEnabled(False)

    def bing_search(self,plain_text_edit:QPlainTextEdit):
        """Bing搜索

        :param plain_text_edit: PySide6 QPlainTextEdit
        """
        search_text  = plain_text_edit.textCursor().selectedText()
        QDesktopServices.openUrl(f"https://cn.bing.com/search?q={search_text}")
        

notepad_main.py没有变化,所以沿用上一个

6.4.3 实现效果

PySide6 搜索功能演示

waylangx11windows都一些区别:

  • 没有打开默认浏览器: 都会直接打开浏览器并搜索
  • 已经打开并最小化浏览器:x11windows都会再次弹出浏览器窗口,而wayland只是有提示弹窗
  • windows不会报错,x11提示缺少文件

6.5 查找相关

需要实现如下功能:

  1. 查找相关行为是否可用:查找、查找上一个、查找下一个
  2. 查找功能: 查找上一个与下一个
  3. 查找对话框: 结合查找功能

为了方便查找相关功能的实现,我们使用将自定义一个纯文本编辑

6.5.1 查找行为是否可用

实现逻辑:

  • 自定义一个信号,用于检测当文本改变时候是否有内容(空字符串也算)
  • 当有内容则行为可用

实现代码:
custom_plain_text_edit.py

from PySide6.QtWidgets import QPlainTextEdit
from PySide6.QtCore import Signal

class PlainTextEdit(QPlainTextEdit):
    """纯文本编辑

    :param QPlainTextEdit: PySide6 QPlainTextEdit
    """
    hasText = Signal(bool)

    def __init__(self):
        """初始化
        """
        super().__init__()
        # 基于文本改变 检测是否有内容
        self.textChanged.connect(self.__has_text)
    
    def __has_text(self):
        """判断是否有文本

        :param plain_text_edit: 纯文本编辑
        """
        self.hasText.emit(True) if self.toPlainText() else self.hasText.emit(False)
    

注意信号必需声明为类变量;借助文本改变信号来判断文本内容是否为空,并发送信号

notepad_main.py:删除导入QPlainTextEdit添加导入from custom_plain_text_edit import PlainTextEdit;修改QPlainTextEdit()PlainTextEdit()

custom_menu.py

from PySide6.QtWidgets import QMenu
from PySide6.QtGui import QKeySequence,QGuiApplication,QDesktopServices
from custom_plain_text_edit import PlainTextEdit

class FileMenu(QMenu):
    """文件菜单

    :param QMenu: PySide6 菜单类
    """
    pass

class EditMenu(QMenu):
    """编辑菜单

    :param QMenu: PySide6 菜单类
    """
    def __init__(self):
        """初始化
        """
        super().__init__()
        self.setup_ui()
    
    def setup_ui(self):
        """设置菜单项
        """
        self.setTitle("编辑(&E)",)
        self.undo = self.addAction("撤销(&U)",QKeySequence.StandardKey.Undo)
        self.addSeparator()
        self.cut =  self.addAction("剪切(&T)",QKeySequence.StandardKey.Cut)
        self.copy = self.addAction("复制(&C)",QKeySequence.StandardKey.Copy)
        self.paste = self.addAction("粘贴(&P)",QKeySequence.StandardKey.Paste)
        self.delete = self.addAction("删除(&L)",QKeySequence.StandardKey.Delete)
        self.addSeparator()
        self.search =  self.addAction("使用Bing搜索")
        self.find_ = self.addAction("查找(&F)",QKeySequence.StandardKey.Find)
        self.find_next = self.addAction("查找下一个(&N)",QKeySequence.StandardKey.FindNext)
        self.find_previous =  self.addAction("查找上一个(&V)",QKeySequence.StandardKey.FindPrevious)
        replace =  self.addAction("替换(&R)",QKeySequence.StandardKey.Replace)
        goto =self.addAction("转到(&G)","Ctrl+G")
        self.addSeparator()
        self.select_all = self.addAction("全选(&A)",QKeySequence.StandardKey.SelectAll)
        date_ = self.addAction("时间/日期(&D)","F5")

        # 默认状态  撤销、剪切、复制、粘贴、删除 、搜索、查找、查找上一个、查找下一个 不可用
        self.undo.setEnabled(False)
        self.cut.setEnabled(False)
        self.copy.setEnabled(False)
        self.paste.setEnabled(False)
        self.delete.setEnabled(False)
        self.search.setEnabled(False)
        self.find_.setEnabled(False)
        self.find_next.setEnabled(False)
        self.find_previous.setEnabled(False)

        # 初始化剪贴板
        self.clipbaord_ = QGuiApplication.clipboard()

    def set_event_bind(self,plain_text_edit:PlainTextEdit):
        """设置必应搜索

        :param plain_text_edit: PySide6 QPlainTextEdit
        """
        # 设置状态 撤销、剪切、复制、粘贴、删除、搜索、查找、查找下一个、查找上一个
        plain_text_edit.undoAvailable.connect(self.undo.setEnabled)
        plain_text_edit.copyAvailable.connect(self.cut.setEnabled)
        plain_text_edit.copyAvailable.connect(self.copy.setEnabled)
        self.clipbaord_.dataChanged.connect(self.reset_paste_state)
        plain_text_edit.copyAvailable.connect(self.delete.setEnabled)
        plain_text_edit.copyAvailable.connect(self.search.setEnabled)
        plain_text_edit.hasText.connect(self.find_.setEnabled)
        plain_text_edit.hasText.connect(self.find_next.setEnabled)
        plain_text_edit.hasText.connect(self.find_previous.setEnabled)

        # 撤销、剪切、复制、粘贴、删除 、全选  搜索行为的绑定
        self.undo.triggered.connect(plain_text_edit.undo)
        self.cut.triggered.connect(plain_text_edit.cut)
        self.copy.triggered.connect(plain_text_edit.copy)
        self.paste.triggered.connect(plain_text_edit.paste)
        self.delete.triggered.connect(plain_text_edit.clear)
        self.select_all.triggered.connect(plain_text_edit.selectAll)
        self.search.triggered.connect(lambda: self.bing_search(plain_text_edit))

    def reset_paste_state(self):
        """重新设置粘贴状态
        """
        clipbaord_text = self.clipbaord_.text()
        if clipbaord_text:
            self.paste.setEnabled(True)
        else:
            self.paste.setEnabled(False)

    def bing_search(self,plain_text_edit:PlainTextEdit):
        """Bing搜索

        :param plain_text_edit: PySide6 QPlainTextEdit
        """
        search_text  = plain_text_edit.textCursor().selectedText()
        QDesktopServices.openUrl(f"https://cn.bing.com/search?q={search_text}")
                 

6.5.2 查找对话框与查找功能

未完待续

6.6 替换与转到

未完待续

6.7 插入日期时间

这里会插入一个类似16:21 2025/11/02的时间格式

6.7.1 实现逻辑与代码

实现逻辑

  1. 借助QDateTime.currentDateTime() 获取当前时间
  2. 将获取的时间转为需要的格式
  3. 插入该时间格式到文本编辑中

注意:使用的是自定义时间格式 hh:mm yyyy/MM/ddhh24小时;mm60分钟;yyyy:年份;MM:月份;dd:日;

custom_plain_text_edit.py 添加如下方法:

    def insert_date_time(self):
        """插入日期时间
        """
        currentDateTime = QDateTime.currentDateTime()
        formattedTime = currentDateTime.toString("hh:mm yyyy/MM/dd")
        self.plainTextEdit.insertPlainText(formattedTime)

custom_menu.py添加如下:

self.date_ .triggered.connect(plain_text_edit.insert_date_time)
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐