我有一个QGraphicsView,其中包含一些QGraphicsItem,我有一个特性(隐藏项),鼠标右键单击,隐藏所需的QGraphicsItem(矩形)及其连接的polylines。我也有一个Undo-Redo特性。
撤销-它应该取消执行的最后一个命令的效果,并显示以前的转换。
重做-它将撤销以前的撤销。
为了实现这个Undo-Redo特性,我使用了Command pattern。我已经为Undo-Redo实现了ZoomIn-ZoomOut特性。
的问题是:我不知道如何为隐藏特性实现撤销-重做。意思是把什么推到堆栈里,拉什么?
下面的Undo-Redo代码是ZoomIn-ZoomOut特性的代码。(为了便于参考,我想实现这样的Hide特性。)
myCommand.c
class myCommand: public QUndoCommand
{
public:
myCommand();
myCommand(double scale, QGraphicsScene* scene,QGraphicsView* view);
private:
QGraphicsItem* mItem;
QGraphicsScene* mScene;
QGraphicsView* mView;
double scaleFactor;
void undo();
void redo();
}myCommand.cpp
myCommand::myCommand(double scale, QGraphicsScene *scene,QGraphicsView* view): mScene(scene),
mView(view),scaleFactor(scale)
{}
void guiCommand::undo()
{
mView->scale(1/scaleFactor,1/scaleFactor);
}
void myCommand::redo()
{
mView->scale(scaleFactor,scaleFactor);
}myView.cpp
void myView::ZoomIn()
{
double scaleFactor = 1.1;
view->scale(scaleFactor,scaleFactor);
myCommand* command1 = new myCommand(scaleFactor,scene,view);
undoStack->push(command1);
}myView.h
public:
QUndoStack* undoStack; 新增:
void myRect::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
vPtr = this->getPtr();
if(vPtr->isVisible == false)
this->hide();
else
{
this->show();
qDebug()<<"Undo Rect";
}
}myCommand是:
myCommand* command3 = new myCommand(isRectHiddden,vPtr,GraphName);
undoStack->push(command3);发布于 2022-04-28 09:35:29
考虑到您已经成功地实现了缩放/缩放,这应该非常简单。
class HideItemCommand: public QUndoCommand
{
public:
explicit HideItemCommand(QGraphicsItem *item);
private:
QGraphicsItem* mItem;
void undo();
void redo();
}HideItemCommand::HideItemCommand(QGraphicsItem *item): mItem(item)
{}
void HideItemCommand::undo()
{
mItem->show();
}
void myCommand::redo()
{
mItem->hide();
}void myView::hideItem(QGraphicsItem* item)
{
item->hide();
auto cmd = new HideItemCommand(item);
undoStack->push(cmd);
}所以这很简单。但是!现在我要考虑向前走一两步。您只询问了如何显示/隐藏撤销/重做,这可以使用我建议的代码来实现。但是您可能正在开发一些绘图应用程序,所以我想您迟早会想要添加项或删除项可撤消/可还原的命令。然后我写的代码就不够了。原因是,如果删除并使用undo/redo重新添加项,则按指针保存项将不再工作。在重新执行删除操作后,指向新重新创建的对象的指针将与先前删除的对应对象的指针不同,因此通过指针保存在HideCommand中的项将无效。
要解决这个无效指针的问题,您需要发明一些其他方法来记录场景中的项目。例如,一些UUID或仅仅是一个整数序列(这就是我要做的),让我们称它为item ID,然后保持这些项目ID和相应指针的双向映射,这样您就可以在那里和后面将ID转换为项指针。
然后,当您通过一些AddItemCommand创建一个项目时,您将创建该项目并生成它的ID,并存储ID和指向映射的指针之间的关系。将此ID的记录放入undo命令中。对于需要引用该项的所有其他命令(例如,HideCommand),您将使用ID而不是指针。这将允许您将所有命令放到堆栈中,使用稳定的ID而不是易失性指针,这些指针可能在撤消/重做、添加或删除对象时发生更改。此外,RemoveItemCommand将记录已删除对象的ID,如果取消,将创建新项(即新的、不同的指针),但使用旧的已知ID。因此引用此ID的其他命令仍然有效。
我希望我能解释清楚。事实上,这并没有那么困难。您只需要理解,如果使用undo/redo添加或删除项,则指针将随着时间的推移而改变,但是ID可以保持不变。为此,需要在命令中而不是指针中保留ID。这当然会改变我写的代码。但我相信,一旦您在应用程序中实现ID <->指针映射,您就可以将它从使用指针调整到使用ID。
https://stackoverflow.com/questions/72039002
复制相似问题