使用QT中的命令模式用于FITINVIEW功能

发布于 2025-01-27 05:27:00 字数 2211 浏览 3 评论 0 原文

我有 qgraphicsview ,其中包含一些 qgraphicsItem 。此视图具有一些功能,例如 Zoom-In Zoom-out Fitin undo-redo 。<
我的 fitin 功能在 undo-redo 功能中不起作用。

使用了命令pattern

class myCommand: public QUndoCommand
{
public:
    myCommand();
    myCommand(QTransform t, int hr, int vr, QGraphicsView* v);
    void undo();
    void redo();
    QTransform t;
    int hScrollBar;
    int  vScrollBar;
    QGraphicsView* mView;
};

(要

myCommand::myCommand(QTransform t, int hr, int vr, QGraphicsView *v)
{
    this->t = t;
    this->hScrollBar= hr;
    this->vScrollBar= vr;
    this->mView = v;
}

void myCommand::undo()
{
    mView->setTransform(t);
    mView->horizontalScrollBar()->setValue(hScrollBar);
    mView->verticalScrollBar()->setValue(vScrollBar);
}

void myCommand::redo()
{
   myView mv;
   mv.FitInView();
}

在qt中

 void myView::FitIn()
    {
        FitInView();
        QTransform t = view->transform();
        int hrValue = view->horizontalScrollBar()->value();
        int vrValue = view->verticalScrollBar()->value();
        myCommand* Command1 = new myCommand(t,hrValue,vrValue,view);
        undoStack->push(Command1);   
    }

void myView::DrawDesign()
{
   // Logic for inserting all the Rectangles and polylines.
   QTimer::singleShot(100, this, [&]() {
        FitInView();
    });
}

void myView::FitInView()
{
    QRectF bounds = scene->sceneRect();
    QRectF rect  {0,0,200,200};
    if (bounds.width() < 200)
    {
        rect .setWidth(bounds.width());
        bounds.setWidth(200);
    }
    if (bounds.height() < 200)
    {
        rect.setWidth(bounds.height());
        bounds.setHeight(200);
    }
    view->fitInView(bounds, Qt::KeepAspectRatio);
    view->updateGeometry();
}

public:
      QUndoStack* undoStack;

实现 undo-redo 非常适合我的设计,但它在 undo-redo 功能中不起作用。
我想我在 myCommand :: undo() mycommand :: redo()函数中犯了一个错误。

I have QGraphicsView which contains some QGraphicsItem. This view has some feature like zoom-in, zoom-out, fitIn, Undo-Redo.
My fitIn feature is not working in Undo-Redo functionality.
( To implement Undo-Redo I have used Command-Pattern in Qt. )

myCommand.h

class myCommand: public QUndoCommand
{
public:
    myCommand();
    myCommand(QTransform t, int hr, int vr, QGraphicsView* v);
    void undo();
    void redo();
    QTransform t;
    int hScrollBar;
    int  vScrollBar;
    QGraphicsView* mView;
};

myCommand.cpp

myCommand::myCommand(QTransform t, int hr, int vr, QGraphicsView *v)
{
    this->t = t;
    this->hScrollBar= hr;
    this->vScrollBar= vr;
    this->mView = v;
}

void myCommand::undo()
{
    mView->setTransform(t);
    mView->horizontalScrollBar()->setValue(hScrollBar);
    mView->verticalScrollBar()->setValue(vScrollBar);
}

void myCommand::redo()
{
   myView mv;
   mv.FitInView();
}

myView.cpp

 void myView::FitIn()
    {
        FitInView();
        QTransform t = view->transform();
        int hrValue = view->horizontalScrollBar()->value();
        int vrValue = view->verticalScrollBar()->value();
        myCommand* Command1 = new myCommand(t,hrValue,vrValue,view);
        undoStack->push(Command1);   
    }

void myView::DrawDesign()
{
   // Logic for inserting all the Rectangles and polylines.
   QTimer::singleShot(100, this, [&]() {
        FitInView();
    });
}

void myView::FitInView()
{
    QRectF bounds = scene->sceneRect();
    QRectF rect  {0,0,200,200};
    if (bounds.width() < 200)
    {
        rect .setWidth(bounds.width());
        bounds.setWidth(200);
    }
    if (bounds.height() < 200)
    {
        rect.setWidth(bounds.height());
        bounds.setHeight(200);
    }
    view->fitInView(bounds, Qt::KeepAspectRatio);
    view->updateGeometry();
}

myView.h

public:
      QUndoStack* undoStack;

FitInView fits my design perfectly but it does not work in Undo-Redo feature.
I think I am making a mistake in myCommand::undo() and myCommand::redo() function.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

迷乱花海 2025-02-03 05:27:00

基于您在

命令模式基于以下想法。
通过创建命令对象实例来完成应用程序。命令
对象将更改应用于文档并存储在命令上
堆。此外,每个命令都知道如何撤消其更改以使文档回到以前的状态。 [ 1 ]


因此,所有更改都应在 qundocommand ),ie内部 qundocommand :: redo 。将命令推到 Qundostack 上后,使用 <代码> Qundostack :: push ,自动执行更改(即 qcommand :: redo ):

按堆栈上的 cmd 将其与最近执行的命令合并。在任何一种情况下,执行 cmd 通过调用其redo()函数。 [ 4 ]

创建一个新的 qundocommand

  1. 实现 qundocommand :: redo redo (而不是某个地方) 的步骤别的)。
  2. Qundocommand :: undo 中写入此命令的倒数。如果需要,请捕获 Qundocommand 构造函数中的初始状态,以轻松恢复 Qundocommand :: redo

应用于您的示例

,因此, myview :: Fitin 应该执行的唯一动作是在撤消堆栈上推动命令:

void myView::FitIn()
{
    undoStack->push(new fitCommand(view));   
}

在REDO命令中实现更改:

void fitCommand::redo()
{
    mView->FitInView(); // Can be implemented using QGraphicsView::fitInView
}

因为拟合的逆操作不是唯一的定义,我们将初始状态存储在 Qundocommand 构造函数(能够恢复 Qundocommand :: undo )内部的初始状态

fitCommand::fitCommand(myView *view)
{
    this->t = view->transform();
    this->hScrollBar= view->horizontalScrollBar()->value();
    this->vScrollBar= view->verticalScrollBar()->value();
    this->mView = view;
}

: 命令恢复 redo 命令:

void fitCommand::undo()
{
    mView->setTransform(t);
    mView->horizontalScrollBar()->setValue(hScrollBar);
    mView->verticalScrollBar()->setValue(vScrollBar);
}

有用的读取材料:

Based on the many question you posted on the Qt's Undo Framework, it seems to me you are missing an essential part of the Command pattern:

The Command pattern is based on the idea that all editing in an
application is done by creating instances of command objects. Command
objects apply changes to the document and are stored on a command
stack. Furthermore, each command knows how to undo its changes to bring the document back to its previous state. [1]

So all changes, should be implemented inside the QUndoCommand (follow the link to discover a basic usage example), i.e. inside QUndoCommand::redo. Once the command is pushed on the QUndoStack, using QUndoStack::push, the change (i.e. QCommand::redo) is automatically performed:

Pushes cmd on the stack or merges it with the most recently executed command. In either case, executes cmd by calling its redo() function. [4]

Steps to create a new QUndoCommand

  1. Implement the desired changes inside QUndoCommand::redo (and not somewhere else).
  2. Write the inverse of this command inside QUndoCommand::undo. If needed, capture the initial state inside the QUndoCommand constructor, to easily revert QUndoCommand::redo.

Applied to your example

So, the only action that myView::FitIn should perform, is pushing the command on the undo stack:

void myView::FitIn()
{
    undoStack->push(new fitCommand(view));   
}

Implement your changes inside the redo command:

void fitCommand::redo()
{
    mView->FitInView(); // Can be implemented using QGraphicsView::fitInView
}

As the inverse operation of fitting is not uniquely defined, we store the initial state inside the QUndoCommand constructor (to be able to restore the initial state inside QUndoCommand::undo):

fitCommand::fitCommand(myView *view)
{
    this->t = view->transform();
    this->hScrollBar= view->horizontalScrollBar()->value();
    this->vScrollBar= view->verticalScrollBar()->value();
    this->mView = view;
}

Now we can implement the undo command to revert the redo command:

void fitCommand::undo()
{
    mView->setTransform(t);
    mView->horizontalScrollBar()->setValue(hScrollBar);
    mView->verticalScrollBar()->setValue(vScrollBar);
}

Usefull reading material:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文