PyQt5中的QAction

参考

声明:本文大部分内容来自网络。
参考1:https://blog.youkuaiyun.com/seniorwizard/article/details/109820641
参考2:https://zhuanlan.zhihu.com/p/32407887/

QAction简要说明

  • 在一个典型的GUI程序中,在用户界面上,常常使用不同的操作方式来完成同一个事情。
  • 例如在一个应用中创建一个新文件,可以使用菜单条里的"文件"–>"新建"菜单项来完成,也可以点击工具栏上的"新建文件"图标(为一个QToolButton),或者是使用快捷键来完成这个动作。
  • PyQt提供QAction类来封装用户需要执行的动作,这样不管是菜单栏,抑或是工具条栏,还是快捷键,都可以独立地和和这个动作相关联。
  • 这样就很好地做到了界面操作方式和具体行为动作的分离,代码之间的耦合性减少,可维护性良好。一句话,QAction是一个用于菜单栏、工具栏或自定义快捷键的抽象动作行为。

QAction常用方法

方法说明
setIcon()设置图标
setText()设置要显示的文字
setToolTip()设置提示文字
setShortcut()设置快捷键
setCheckable()设置成check选择模式
setChecked()设置成选中/未选中(菜单前打勾或不打勾)

QAction常用信号

方法说明
triggered点击时发射信号,( 最常用)
hovered鼠标悬浮上空时发射该信号
toggled如果状态为选中,则checked为True,该参数会被发送
changed只要QAction状态发生改变就会发送,如多了个图标,换了文字等

QAction举例

  • 在建立menuBar中增加menu时,或者创建QAction对象时,可以直接指定快捷键,addMenu(‘文件(&F)’),act_file_open = QAction(‘打开(&O)…’, self)。
  • 设置图标的时候,可以用标准图标,如setIcon(QApplication.style().standardIcon(QStyle.SP_FileIcon))
  • 另一种设置快捷键的方式:setShortcut(Qt.CTRL + Qt.Key_N)
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QApplication, QMainWindow,
                             QAction, QPlainTextEdit, QStyle, QFileDialog,
                             QMessageBox)


class ToolButton(QMainWindow):
    def __init__(self):
        super().__init__()
        self.path = None
        self.setWindowTitle("ToolButton and QAction Demo")
        self.resize(500, 400)
        self.init_ui()

    def init_ui(self):
        # 设置一个文本编辑器作为中心小部件, setCentralWidget设置窗口中心部件
        self.text_editor = QPlainTextEdit(self)
        self.setCentralWidget(self.text_editor)

        mbar = self.menuBar()
        m_file = mbar.addMenu('文件(&F)')
        m_edit = mbar.addMenu('编辑(&E)')
        m_format = mbar.addMenu('格式(&O)')
        m_help = mbar.addMenu('帮助(&H)')
        style = QApplication.style()

        # -------------------------------- 文件操作部分 -------------------------------- #
        # 新建文件
        act_file_new = QAction('新建(&N)', self)
        act_file_new.setIcon(style.standardIcon(QStyle.SP_FileIcon))
        act_file_new.setShortcut(Qt.CTRL + Qt.Key_N)
        act_file_new.triggered.connect(self.slot_file_new)
        m_file.addAction(act_file_new)

        # 打开文件
        act_file_open = QAction('打开(&O)...', self)
        act_file_open.setIcon(style.standardIcon(QStyle.SP_DialogOpenButton))
        act_file_open.setShortcut(Qt.CTRL + Qt.Key_O)
        act_file_open.triggered.connect(self.slot_file_open)
        m_file.addAction(act_file_open)
        
        # 保存
        act_file_save = QAction('保存(&S)', self)
        act_file_save.setIcon(style.standardIcon(QStyle.SP_DialogSaveButton))
        act_file_save.setShortcut(Qt.CTRL + Qt.Key_S)
        act_file_save.triggered.connect(self.slot_file_save)
        m_file.addAction(act_file_save)

        # 另存为
        act_file_saveas = QAction('另存为(&A)...', self)
        act_file_saveas.triggered.connect(self.slot_file_saveas)
        m_file.addAction(act_file_saveas)
        m_file.addSeparator()

        # 退出菜单
        aFileExit = QAction('退出(&X)', self)
        aFileExit.triggered.connect(self.close)
        m_file.addAction(aFileExit)

        # -------------------------------- 编辑部分 -------------------------------- #
        # 撤销编辑
        act_edit_undo = QAction('撤销(&U)', self)
        act_edit_undo.setShortcut(Qt.CTRL + Qt.Key_Z)
        act_edit_undo.triggered.connect(self.text_editor.undo)
        m_edit.addAction(act_edit_undo)

        # 恢复编辑
        aEditRedo = QAction('恢复(&R)', self)
        aEditRedo.setShortcut(Qt.CTRL + Qt.Key_Y)
        act_edit_undo.triggered.connect(self.text_editor.redo)
        m_edit.addAction(aEditRedo)
        m_edit.addSeparator()

        # 剪切操作
        act_edit_cut = QAction('剪切(&T)', self)
        act_edit_cut.setShortcut(Qt.CTRL + Qt.Key_X)
        act_edit_cut.triggered.connect(self.text_editor.cut)
        m_edit.addAction(act_edit_cut)

        # 复制操作
        act_edit_copy = QAction('复制(&C)', self)
        act_edit_copy.setShortcut(Qt.CTRL + Qt.Key_C)
        act_edit_copy.triggered.connect(self.text_editor.copy)
        m_edit.addAction(act_edit_copy)

        # 粘贴操作
        act_edit_paste = QAction('粘贴(&P)', self)
        act_edit_paste.setShortcut(Qt.CTRL + Qt.Key_V)
        act_edit_paste.triggered.connect(self.text_editor.paste)
        m_edit.addAction(act_edit_paste)
        
        # 删除操作
        act_edit_del = QAction('删除(&L)', self)
        act_edit_del.setShortcut(Qt.Key_Delete)
        act_edit_del.triggered.connect(self.slot_edit_delete)
        m_edit.addAction(act_edit_del)
        m_edit.addSeparator()

        # 全选操作
        act_edit_select_all = QAction('全选(&A)', self)
        act_edit_select_all.setShortcut(Qt.CTRL + Qt.Key_A)
        act_edit_select_all.triggered.connect(self.text_editor.selectAll)
        m_edit.addAction(act_edit_select_all)

        # ==== 格式设置部分 ==== #
        act_fmt_auto_line = QAction('自动换行(&W)', self)
        act_fmt_auto_line.setCheckable(True)
        act_fmt_auto_line.setChecked(True)
        act_fmt_auto_line.triggered.connect(self.slot_format_auto_line)
        m_format.addAction(act_fmt_auto_line)

        # ==== 帮助部分 ==== #
        act_help_about = QAction('关于(&A)...', self)
        act_help_about.triggered.connect(self.slot_help_about)
        m_help.addAction(act_help_about)

    def msg_critical(self, strInfo):
        dlg = QMessageBox(self)
        dlg.setIcon(QMessageBox.Critical)
        dlg.setText(strInfo)
        dlg.show()

    def slot_file_new(self):
        self.text_editor.clear()

    def slot_file_open(self):
        path, _ = QFileDialog.getOpenFileName(self, '打开文件', '', '文本文件 (*.txt)')
        if path:
            try:
                with open(path, 'rU') as f:
                    text = f.read()
            except Exception as e:
                self.msg_critical(str(e))
            else:
                self.path = path
                self.text_editor.setPlainText(text)

    def slot_file_save(self):
        if self.path is None:
            return self.slot_file_saveas()
        self._saveToPath(self.path)

    def slot_file_saveas(self):
        path, _ = QFileDialog.getSaveFileName(self, '保存文件', '', '文本文件 (*.txt)')
        if not path:
            return self._slot_save_to_path(path)

    def _slot_save_to_path(self, path):
        text = self.text_editor.toPlainText()
        try:
            with open(path, 'w') as f:
                f.write(text)
        except Exception as e:
            self.msg_critical(str(e))
        else:
            self.path = path

    def slot_edit_delete(self):
        tc = self.text_editor.textCursor()
        # tc.select(QtGui.QTextCursor.BlockUnderCursor) 这样删除一行
        tc.removeSelectedText()

    def slot_format_auto_line(self, autoLine):
        if autoLine:
            self.text_editor.setLineWrapMode(QPlainTextEdit.WidgetWidth)
        else:
            self.text_editor.setLineWrapMode(QPlainTextEdit.NoWrap)

    def slot_help_about(self):
        QMessageBox.information(self, '实战PyQt5', 'PyQt5实现的文本编辑器演示版')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = ToolButton()
    window.show()
    sys.exit(app.exec())
<think>好的,用户想知道PyQt5QAction的父对象是什么。我需要先回顾一下PyQt5的文档和相关引用内容。 首先,QAction是用于菜单项、工具栏按钮等的动作类。根据引用[3]和[5],用户可能在代码中创建QAction时没有显式设置父对象,或者父对象设置不正确导致问题。比如引用[5]中的例子,创建QAction时没有指定父对象,但之后将其添加到QToolButton,可能父对象由按钮自动设置?不过需要确认。 QAction的父对象通常是在构造函数中指定的。父对象负责管理子对象的内存,当父对象销毁时,子对象也会被自动删除。如果用户没有指定父对象,可能会导致内存泄漏或意外行为。 比如,在引用[5]的代码中,创建QAction时没有指定父对象,但之后将其设置为QToolButton的默认动作。这时候QToolButton是否会成为QAction的父对象?或者需要显式设置? 查阅PyQt5文档,当QAction被添加到某个控件(如QToolButton、QMenu)时,该控件会成为QAction的父对象。但不确定是否总是如此。比如,当使用addAction()方法时,父对象是否自动设置? 另外,引用[1]中提到的问题,用户可能没有正确设置父对象导致信号槽连接失败。虽然那个例子是关于connectSlotsByName的,但父对象关系可能影响对象的命名和查找。 总结:QAction的父对象通常在创建时指定,或者在添加到父控件时自动设置。正确设置父对象有助于内存管理和信号槽的连接。用户需要确保在创建QAction时正确传递父对象参数,或者在添加到父控件后父对象被正确关联。</think>在PyQt5中,**QAction的父对象通常与其关联的控件相关**。根据设计需求,QAction的父对象可以是以下两种类型: --- ### 1. 显式指定父对象 在创建`QAction`时,可以通过构造函数直接指定父对象: ```python action = QAction("文本", parent=父控件对象) ``` - **父控件对象**通常是包含该动作的窗口、菜单栏或工具栏(例如`QMainWindow`、`QMenu`等) - 父对象负责管理子对象生命周期,父对象销毁时子对象自动销毁[^2] 示例: ```python class MyWindow(QMainWindow): def __init__(self): super().__init__() # 指定父对象为当前窗口 self.action = QAction("保存", parent=self) ``` --- ### 2. 隐式关联父对象 当通过控件方法创建动作时,父对象会自动关联: ```python menu = QMenu("文件") action = menu.addAction("新建") # 此时父对象是menu ``` 或通过控件添加动作: ```python toolbar = QToolBar() action = QAction("打开", self) # 父对象是当前窗口 toolbar.addAction(action) # action的父对象仍为窗口,但被工具栏管理 ``` --- ### 关键区别 | 方式 | 父对象管理权 | 典型应用场景 | |------------|--------------------------|---------------------------| | 显式指定 | 直接由指定父对象管理 | 独立动作或跨多个控件复用的动作 | | 隐式关联 | 由添加动作的控件管理 | 菜单项、工具栏按钮等特定控件 | --- ### 常见问题解决 如果遇到**信号无法触发**的情况(如引用[1]中的问题),需检查: 1. 父对象是否存活(未被提前销毁) 2. 是否通过`addAction()`正确关联控件 3. 对象命名是否符合`on_对象名_信号名`的自动连接规则[^1][^3] ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值