【QA】Qt中有哪些命令模式的运用?

news2025/3/26 15:18:04

在 C++/Qt 中,命令模式(Command Pattern)的实现通常用于封装操作请求、支持撤销/重做(Undo/Redo)或解耦调用者与接收者。以下是几种常见的实现方式及示例:


1. Qt 的 QUndoCommandQUndoStack(内置的撤销/重做框架)

这是 Qt 中命令模式的最典型实现,用于管理可撤销的操作。

  • 核心类

    • QUndoCommand:基类,表示一个可撤销的命令,需实现 undo()redo()
    • QUndoStack:管理命令历史记录的栈,支持撤销/重做。
  • 示例代码

    class AddItemCommand : public QUndoCommand {
    public:
        AddItemCommand(QListWidget *listWidget, const QString &text, QUndoCommand *parent = nullptr)
            : QUndoCommand("Add Item", parent), m_listWidget(listWidget), m_text(text) {}
        
        void redo() override {
            m_listWidget->addItem(m_text);
        }
        
        void undo() override {
            QListWidgetItem *item = m_listWidget->takeItem(m_listWidget->count() - 1);
            delete item;
        }
    
    private:
        QListWidget *m_listWidget;
        QString m_text;
    };
    
    // 使用示例
    QUndoStack undoStack;
    QListWidget listWidget;
    
    // 执行命令
    undoStack.push(new AddItemCommand(&listWidget, "New Item"));
    
    // 撤销
    undoStack.undo();
    
    // 重做
    undoStack.redo();
    

2. Qt 的 QAction(动作框架)

QAction 封装了用户触发的操作(如菜单项点击),可绑定到多个控件(菜单、工具栏按钮等),本质上是命令模式的轻量级应用。

  • 核心思想

    • QAction 将操作(如“复制”)封装为对象,通过信号 triggered() 触发执行。
    • 可绑定快捷键、图标、文本等,统一管理状态(启用/禁用)。
  • 示例代码

    QAction *copyAction = new QAction("Copy", this);
    copyAction->setShortcut(QKeySequence::Copy);
    connect(copyAction, &QAction::triggered, this, &MyWidget::copy);
    
    // 将动作添加到菜单和工具栏
    menuBar()->addAction(copyAction);
    toolBar()->addAction(copyAction);
    

3. 自定义命令接口(通用实现)

若需更灵活的控制,可自定义命令基类,并手动管理命令队列。

  • 实现步骤

    1. 定义抽象命令接口。
    2. 实现具体命令类。
    3. 使用调用者(Invoker)触发命令。
  • 示例代码

    // 1. 定义命令接口
    class Command {
    public:
        virtual ~Command() {}
        virtual void execute() = 0;
        virtual void undo() = 0;
    };
    
    // 2. 具体命令类:改变文本
    class ChangeTextCommand : public Command {
    public:
        ChangeTextCommand(QLabel *label, const QString &newText)
            : m_label(label), m_oldText(label->text()), m_newText(newText) {}
        
        void execute() override {
            m_label->setText(m_newText);
        }
        
        void undo() override {
            m_label->setText(m_oldText);
        }
    
    private:
        QLabel *m_label;
        QString m_oldText;
        QString m_newText;
    };
    
    // 3. 调用者(如按钮点击触发命令)
    QPushButton button("Change Text");
    QLabel label("Original Text");
    Command *cmd = new ChangeTextCommand(&label, "New Text");
    
    QObject::connect(&button, &QPushButton::clicked, [cmd]() {
        cmd->execute();
    });
    

4. 信号与槽的封装

通过将槽函数包装为命令对象,结合 QObject::connect 实现解耦。

  • 示例场景

    • 将复杂操作封装为命令对象,通过信号触发执行。
    • 使用 QSharedPointer 管理命令生命周期。
    class CommandWrapper : public QObject {
        Q_OBJECT
    public:
        CommandWrapper(Command *cmd) : m_cmd(cmd) {}
    
    public slots:
        void execute() { m_cmd->execute(); }
        void undo() { m_cmd->undo(); }
    
    private:
        QSharedPointer<Command> m_cmd;
    };
    
    // 连接信号到命令
    CommandWrapper wrapper(new ChangeTextCommand(&label, "New Text"));
    QObject::connect(&button, &QPushButton::clicked, &wrapper, &CommandWrapper::execute);
    

5. 宏命令(Composite Command)

将多个命令组合成一个宏命令,实现批量操作。

  • 示例代码
    class MacroCommand : public Command {
    public:
        void addCommand(Command *cmd) {
            m_commands.append(cmd);
        }
        
        void execute() override {
            for (auto cmd : m_commands) {
                cmd->execute();
            }
        }
        
        void undo() override {
            for (auto it = m_commands.rbegin(); it != m_commands.rend(); ++it) {
                (*it)->undo();
            }
        }
    
    private:
        QList<Command*> m_commands;
    };
    
    // 使用示例
    MacroCommand *macro = new MacroCommand;
    macro->addCommand(new Command1);
    macro->addCommand(new Command2);
    macro->execute();
    

总结

在 Qt 中应用命令模式的核心思想是:

  1. 封装操作:将请求封装为对象(如 QUndoCommand)。
  2. 解耦调用者与接收者:通过信号/槽或直接调用命令接口。
  3. 支持扩展:通过组合或继承实现复杂逻辑(如宏命令)。

根据需求选择合适的方式,若需要撤销/重做,优先使用 QUndoStack;若需简单解耦,可通过 QAction 或自定义命令类实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2320882.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Cocos Creator Shader入门实战(五):材质的了解、使用和动态构建

引擎&#xff1a;3.8.5 您好&#xff0c;我是鹤九日&#xff01; 回顾 前面的几篇文章&#xff0c;讲述的主要是Cocos引擎对Shader使用的一些固定规则&#xff0c;这里汇总下&#xff1a; 一、Shader实现基础是OpenGL ES可编程渲染管线&#xff0c;开发者只需关注顶点着色器和…

vue设置自定义logo跟标题

准备 Logo 图片 将自定义的 Logo 图片&#xff08;如 logo.png&#xff09;放置在项目的 public文件夹下。 使用环境变量设置 Logo 和标题&#xff08;可选&#xff09; 创建或修改 .env 文件 在项目根目录下创建或修改 .env 文件&#xff0c;添加以下内容&#xff1a; VITE_A…

尝试在软考65天前开始成为软件设计师-计算机网络

OSI/RM 七层模型 层次名功能主要协议7应用层实现具体应用功能 FTP(文件传输)、HTTP、Telnet、 POP3(邮件)SMTP(邮件) ------- DHCP、TFTP(小文件)、 SNMP、 DNS(域名) 6表示层数据格式,加密,压缩.....5会话层建立,管理&终止对话4传输层端到端连接TCP,UDP3网络层分组传输&a…

VMware主机换到高配电脑,高版本系统的问题

原来主机是i3 ,windows7系统&#xff0c;vmware 14.0,虚机系统是ubuntu 14.04。目标新机是i7 14700KF,windows11系统。原以为安装虚拟机&#xff0c;将磁盘文件&#xff0c;虚拟机配置文件拷贝过去可以直接用。 新目标主机先安装了vmware 15&#xff0c;运行原理虚机&#xff0…

【Linux内核系列】:动静态库详解

&#x1f525; 本文专栏&#xff1a;Linux &#x1f338;作者主页&#xff1a;努力努力再努力wz &#x1f4aa; 今日博客励志语录&#xff1a; 有些鸟儿是注定是关不住的&#xff0c;因为它们的每一片羽翼都沾满了自由的光辉 ★★★ 本文前置知识&#xff1a; 编译与链接的过程…

windows环境下NER Python项目环境配置(内含真的从头安的perl配置)

注意 本文是基于完整项目的环境配置&#xff0c;即本身可运行项目你拿来用 其中有一些其他问题&#xff0c;知道的忽略即可 导入pycharm基本包怎么下就不说了&#xff08;这个都问&#xff1f;给你一拳o(&#xff40;ω*)o&#xff09; 看perl跳转第5条 1.predict报错多个设备…

IDEA批量替换项目下所有文件中的特定内容

文章目录 1. 问题引入2. 批量替换项目下所有文件中的特定内容2.1 右键项目的根目录&#xff0c;点击在文件中替换2.2 输入要替换的内容 3. 解决替换一整行文本后出现空行的问题4. 增加筛选条件提高匹配的精确度 更多 IDEA 的使用技巧可以查看 IDEA 专栏&#xff1a; IDEA 1. 问…

【蓝桥杯】4535勇闯魔堡(多源BFS + 二分)

思路 k有一个范围&#xff08;0到怪物攻击的最大值&#xff09;&#xff0c;求满足要求的k的最小值。很明显的二分套路。 关键是check函数怎么写&#xff0c;我们需要找到一条从第一行到最后一行的路径&#xff0c;每一次可以从上下左右四个方向前进&#xff0c;那么我么可以用…

HTML图像标签的详细介绍

1. 常用图像格式 格式特点适用场景JPEG有损压缩&#xff0c;文件小&#xff0c;不支持透明适合照片、复杂图像PNG无损压缩&#xff0c;支持透明&#xff08;Alpha通道&#xff09;适合图标、需要透明背景的图片GIF支持动画&#xff0c;最多256色简单动画、低色彩图标WebP谷歌开…

Chapter 4-15. Troubleshooting Congestion in Fibre Channel Fabrics

show zone member: Shows the name of the zone to which a device belongs to. This command can be used to find the victims of a culprit device or vice versa. 显示设备所属的区域名称。该命令可用于查找罪魁祸首设备的受害者,反之亦然。 show zone active: Shows the…

QT三 自定义控件

一 自定义控件 现在的需求是这样&#xff1a; 假设我们要在QWidget 上做定制&#xff0c;这个定制包括了关于 一些事件处理&#xff0c;意味着要重写QWidget的一些代码&#xff0c;这是不实际的&#xff0c;因此我们需要自己写一个MyWidget继承QWidget&#xff0c;然后再MyWi…

在 ASP .NET Core 9.0 中使用 Scalar 创建漂亮的 API 文档

示例代码&#xff1a;https://download.csdn.net/download/hefeng_aspnet/90407900 Scalar 是一款可帮助我们为 API 创建精美文档的工具。与感觉有些过时的默认 Swagger 文档不同&#xff0c;Scalar 为 API 文档提供了全新而现代的 UI。其简洁的设计让开发人员可以轻松找到测试…

用于 RGB-D 显著目标检测的点感知交互和 CNN 诱导的细化网络(问题)

摘要 问题一&#xff1a;但在对自模态和跨模态的全局长距离依赖关系进行建模方面仍显不足。什么意思&#xff1f; 自模态&#xff08;Intra-modal&#xff09;全局依赖&#xff1a;在同一模态内&#xff0c;长距离像素之间的信息交互对于理解全局背景很重要&#xff0c;但 CN…

python3 -m http.sever 8080加载不了解决办法

解决方法很多&#xff0c;本文设置各种处理方法&#xff0c;逻辑上需要根据你的自身情况选择 我会告诉你遇到这种问题怎么做&#xff0c;根据具体症状处理 如需转载&#xff0c;标记出处 背景&#xff1a; 1。如图 2.。域名访问不了 http://www.meiduo.site:8080/register.ht…

Oracle数据库性能优化全攻略:十大关键方向深度解析与实践指南

文章目录 一、SQL查询优化二、索引优化三、内存管理四、I/O优化五、分区表与分区索引六、并行处理七、统计信息管理八、锁与并发控制九、数据库参数调优十、应用设计优化结论 在当今数据驱动的时代&#xff0c;数据库的性能优化成为了确保企业应用高效运行的关键。Oracle作为业…

windows清除电脑开机密码,可保留原本的系统和资料,不重装系统

前言 很久的一台电脑没有使用了&#xff0c;开机密码忘了&#xff0c;进不去系统 方法 1.将一个闲置u盘设置成pe盘&#xff08;注意&#xff0c;这个操作会清空原来u盘的数据&#xff0c;需要在配置前将重要数据转移走&#xff0c;数据无价&#xff0c;别因为配置这个丢了重…

【深度学习】【目标检测】【Ultralytics-YOLO系列】Windows11下YOLOV3人脸检测

【深度学习】【目标检测】【Ultralytics-YOLO系列】Windows11下YOLOV3人脸检测 文章目录 【深度学习】【目标检测】【Ultralytics-YOLO系列】Windows11下YOLOV3人脸检测前言YOLOV3模型运行环境搭建YOLOV3模型运行数据集准备YOLOV3运行模型训练模型验证模型推理导出onnx模型 总结…

html5-qrcode前端打开摄像头扫描二维码功能

实现的效果如图所示&#xff0c;全屏打开并且扫描到二维码后弹窗提醒&#xff0c;主要就是使用html5-qrcode这个依赖库&#xff0c;html5-qrcode开源地址&#xff1a;GitHub - mebjas/html5-qrcode: A cross platform HTML5 QR code reader. See end to end implementation at:…

ui_auto_study(持续更新)

通过where python来找到python解释器的安装目录 如果不适配&#xff0c;谷歌浏览器插件可以在这个地址下载对应的驱动 谷歌浏览器驱动下载地址 下载对应的驱动版本&#xff0c;替换原驱动 替换后&#xff0c;可以执行成功 div代表标签 .开头的代表类# 使用class定位元素 …

【nodejs】爬虫路漫漫,关于nodejs的基操

一.下载安装nodejs 官网地址&#xff1a;Node.js — 在任何地方运行 JavaScript 二.下载安装vscode代码编辑器 官网地址&#xff1a;Download Visual Studio Code - Mac, Linux, Windows 三.修改本地脚本策略 1&#xff0c;windowsi 打开电脑设置 2&#xff0c;输入powersh…