使用 QUndoCommand 的子级/父级推送多个命令以一次撤消堆栈

Posted

技术标签:

【中文标题】使用 QUndoCommand 的子级/父级推送多个命令以一次撤消堆栈【英文标题】:Using children/parent of QUndoCommand to push several commands to undo stack at once 【发布时间】:2015-06-30 21:13:20 【问题描述】:

我正在使用 QUndoStack 实现带有撤消堆栈的可编辑树。删除节点需要删除它的所有后代。我为此使用子 QUndoCommand:

标题:

class RemoveNodeCommand : QUndoCommand

public:
    RemoveNodeCommand(NodesContainer *cont, int node_id, QUndoCommand *parent = 0);
    void undo();
    void redo();

private:
    NodeParams mParams;
    NodesContainer *mCont;
;

命令实现:

RemoveNodeCommand::RemoveNodeCommand(NodesContainer *cont, int node_id, QUndoCommand *parent)

    QList<int> offsprings_ids;
    QUndoCommand *tmpcomm;

    //Keep params of deleted notes to use in Undo if necessary
    mParams = cont->getNogeParams();
    mCont = cont;

    //List all offsprings of node to be deleted
    cont->getOffspringsIds(&offsprings_ids);

    for(int co = 0; co < basket.size(); co++)
    
        tmpcomm = new RemoveNodeCommand(cont, offsprings_ids.at(co), this);
    


void RemoveNodeCommand::redo()

    mCont->deleteNode(mParams);

树编辑类中的槽:

RemoveNodeSlot(int id)

     mUndoStack->push( new RemoveNodeCommand(mContainer, id));

在 QUndoStack 文档中指出 如果 parent 不为 0,则此命令将附加到 parent 的子列表中。, 确实,每次创建新的子命令时,父命令的 child_list 都会增加。 但是,推动父母并不会导致推动所有的孩子。 redo() 仅对父节点调用。 我做错了什么?我需要手动推动所有孩子吗?而且,由于我需要在单个撤消步骤中使用所有这些命令,我​​需要使用 beginMacro 和 endMacro?但是这种方式,在 QUndoCommand 中持有指向子命令的指针是没有意义的。我猜 t 不是 QT 错误,而是我对 undo stack 概念的误解。如何正确使用子命令机制?

【问题讨论】:

【参考方案1】:

在嵌套实现中需要调用 QUndoCommand::undo() 和 QUndoCommand::redo() 的默认实现。 在 redo() 中,必须在处理数据之前添加默认实现,在 undo() 中 - 在所有树数据继续进行之后。

void RemoveNodeCommand::redo()

    QUndoCommand::redo();
    mCont->deleteNode(mParams);

【讨论】:

【参考方案2】:

子命令构造函数需要将parent参数传递给QUndoCommand构造函数:

RemoveNodeCommand::RemoveNodeCommand(NodesContainer *cont, int node_id, QUndoCommand *parent) 
: QUndoCommand(parent) 
// ...

因为您对父子类使用单个类,所以您还需要调用父类的 undo+redo 方法,如 Dmitry Kurgansky 所述

【讨论】:

以上是关于使用 QUndoCommand 的子级/父级推送多个命令以一次撤消堆栈的主要内容,如果未能解决你的问题,请参考以下文章

使用MySQL SELECT查询获取父级的子级

根据显示弹性框中的子级设置父级高度/宽度

MaterialAlertDialogBu​​ilder 崩溃并显示错误:使用自定义视图时,指定的子级已经有父级

Java - 为啥另一个包中的子级无法通过父级引用访问父级的受保护方法?

javascript 从父级中的子级渲染节点更新

从父级中的子级访问元素标记名