QGraphicsView 框架學習(四),Undo Redo

撤銷,重做,任何編輯器的必備工具。還是Qt的提供的標準解決方案。

QUndoCommand;QUndoStack;QUndoView;

圖形編輯的每一個動作都應該有相應的撤銷和重做機制。我們爲每個動作派生一個對象。

Qt demo裏提供了兩個例子,一個是使用QGraphic是View圖形框架的,一個是Qt自己寫的一個簡單的圖形編輯器。

這兩個都可以參考。這裏簡單的描述一下我自己抄來的。

class MoveCommand : public QUndoCommand
{
public:
    MoveCommand(QGraphicsScene *graphicsScene, const QPointF & delta ,
                QUndoCommand * parent = 0);
    void undo() Q_DECL_OVERRIDE;
    void redo() Q_DECL_OVERRIDE;
private:
    QList<QGraphicsItem *> items;
    QGraphicsScene *myGraphicsScene;
    QPointF myDelta;
    bool bMoved;
};

MoveCommand::MoveCommand(QGraphicsScene *graphicsScene, const QPointF &delta, QUndoCommand *parent)
    : QUndoCommand(parent)
{
    items = graphicsScene->selectedItems();
    myDelta = delta;
    myGraphicsScene = graphicsScene;
    bMoved = true;
}

//! [2]
void MoveCommand::undo()
{
    foreach (QGraphicsItem *item, items) {
       item->moveBy(-myDelta.x(),-myDelta.y());
    }
    myGraphicsScene->update();
    setText(QObject::tr("Move %1,%2")
        .arg(-myDelta.x()).arg(-myDelta.y()));
    bMoved = false;
}
//! [2]

//! [3]
void MoveCommand::redo()
{
    if ( !bMoved ){
        foreach (QGraphicsItem *item, items) {
           item->moveBy(myDelta.x(),myDelta.y());
        }
        myGraphicsScene->update();
    }
    setText(QObject::tr("Move %1,%2")
        .arg(myDelta.x()).arg(myDelta.y()));
}

多個對象移動的動作是交給scene處理的,所以這裏認爲這個動作之前對象已經移動過了,在這個類里加了一個bMoved的標記, QUndoStack::push方法默認會調用redo方法,

所以第一次redo是不需要做的,除非做過undo後,再執行redo才能移動對象。

      我們可以創建一個QUndoView來觀察 undoStack裏的動作列表,不過發現如果在裏面跳着執行,undostack會亂套,所以看看就好。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章