Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: perroBasset от Декабрь 21, 2010, 13:00



Название: Undo/Redo в QGraphicsScene
Отправлено: perroBasset от Декабрь 21, 2010, 13:00
Ребята, реализовываю механизм Undo/Redo. Есть график, пользователь таскает точки, все меняется.. соответственно нужно иметь возможность возвращаться вперед и назад.

У меня есть некоторые наработки, но и, как оказывается, ошибки тоже  :-\  Можете пробежаться глазами, сказать, что не так?
Большое мерси!

Код:
void
MainWindow::on_Undo_triggered()
{
    struct State
    {
        QVector<QPointF> Points; // меняются точки кривой, их и сохраняем в состояние
    };

    QQueue<State> undoHistory;
    int currentUndoStep;
    enum { MAX_UNDO_LEVEL = 100 };

    while (currentUndoStep > 0)
    {
          undoHistory.pop_front();
          currentUndoStep--;
    }

    State s;

    s.Points = Points;
    undoHistory.push_front(s);

    if(undoHistory.size() > MAX_UNDO_LEVEL)
    s.pop_back();

    if (currentUndoStep + 1 >= undoHistory.size())
    return;
   
    currentUndoStep++;
    const State& ss = undoHistory[currentUndoStep];
    Points = ss.Points;
}

Соответственно возникают 3 проблемы:
1.  QQueue<State> undoHistory; - не воспринимается. мы же делаем очередь из состояний, что не так?
2.  s.pop_back(); - аналогично. понимаю, что такой функции у s нет, но по-другому  ???
3.  struct State может стоит в заголовочном файле разместить?


Название: Re: Undo/Redo в QGraphicsScene
Отправлено: twp от Декабрь 21, 2010, 13:35
чем не подошел QUndoStack?


Название: Re: Undo/Redo в QGraphicsScene
Отправлено: perroBasset от Декабрь 21, 2010, 13:59
чем не подошел QUndoStack?

Я не разбиралась в нем. Возможно, с его помощью было бы проще..
А что, этот способ не подходит?


Название: Re: Undo/Redo в QGraphicsScene
Отправлено: twp от Декабрь 21, 2010, 17:36
честно сказать не въезжал в код. Просто зачем изобретать велосипед? Ведь лучше один раз разобраться, а потом использовать по назначению в своих проектах


Название: Re: Undo/Redo в QGraphicsScene
Отправлено: frostyland от Декабрь 22, 2010, 10:08
чем не подошел QUndoStack?

Я не разбиралась в нем. Возможно, с его помощью было бы проще..
А что, этот способ не подходит?

Очень рекомендую однажды разобраться.
Вот пара примеров
Qt/demos/undo
Qt/examples\tools\undoframework


Название: Re: Undo/Redo в QGraphicsScene
Отправлено: perroBasset от Январь 29, 2011, 22:40
Ребят, разбираюсь в Undo Framework. Запуталась с командами..
Задача: пользователь двигает вершины какого-то многоугольника (заданы как QGraphicsEllipseItem, имеют порядковый номер и координаты) и, судя по результату, хочет удалить действие или повторить. Короче простейший пример.

Смотрите, если по порядку.
-- создаем очередь, в которой хранятся наши команды и определяем их максимальное число
stack = new QUndoStack();
stack.setUndoLimit(100);

-- создаем команду
movePoints = new QUndoCommand();

Эта команда записывается в очередь, когда пользователь двигает какую-то точку, то есть должна "знать" положение этой точки. Но как это оформить :( В документации копалась, толком не поняла, как именно определять эти команды. Описывать их отдельной функцией и добавлять с помощью .push() в stack?




Название: Re: Undo/Redo в QGraphicsScene
Отправлено: twp от Январь 31, 2011, 11:46
нужно создать свою команду, унаследованную от QUndoCommand и переопределить методы
Код:
virtual void undo()
virtual void redo()
все необходимые данные (исходная точка, целевая точка и все остальное) должны хранится в команде и передаваться как параметр в конструктор. Есть же хороший пример в асистенте:
Код:
 class AppendText : public QUndoCommand
 {
 public:
     AppendText(QString *doc, const QString &text)
         : m_document(doc), m_text(text) { setText("append text"); }
     virtual void undo()
         { m_document->chop(m_text.length()); }
     virtual void redo()
         { m_document->append(m_text); }
 private:
     QString *m_document;
     QString m_text;
 };