📄 4.14 实例:排积木程序.txt
字号:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
public slots:
void itemMoved(DiagramItem *movedDiagram, const QPointF &moveStartPosition);
private slots:
void deleteItem();
void addBox();
void addTriangle();
void about();
void itemMenuAboutToShow();
void itemMenuAboutToHide();
private:
void createActions();
void createMenus();
void createUndoView();
QAction *deleteAction;
QAction *addBoxAction;
QAction *addTriangleAction;
QAction *undoAction;
QAction *redoAction;
QAction *exitAction;
QAction *aboutAction;
QMenu *fileMenu;
QMenu *editMenu;
QMenu *itemMenu;
QMenu *helpMenu;
DiagramScene *diagramScene;
QUndoStack *undoStack;
QUndoView *undoView;
};
MainWindow::MainWindow()
{
undoStack = new QUndoStack();
createActions();
createMenus();
connect(undoStack, SIGNAL(canRedoChanged(bool)),
redoAction, SLOT(setEnabled(bool)));
connect(undoStack, SIGNAL(canUndoChanged(bool)),
undoAction, SLOT(setEnabled(bool)));
createUndoView();
diagramScene = new DiagramScene();
QBrush pixmapBrush(QPixmap(":/images/cross.png").scaled(30, 30));
diagramScene->setBackgroundBrush(pixmapBrush);
diagramScene->setSceneRect(QRect(0, 0, 500, 500));
connect(diagramScene, SIGNAL(itemMoved(DiagramItem *, const QPointF &)),
this, SLOT(itemMoved(DiagramItem *, const QPointF &)));
setWindowTitle("Undo Framework");
QGraphicsView *view = new QGraphicsView(diagramScene);
setCentralWidget(view);
resize(700, 500);
}
void MainWindow::createUndoView()
{
undoView = new QUndoView(undoStack);
undoView->setWindowTitle(tr("Command List"));
undoView->show();
undoView->setAttribute(Qt::WA_QuitOnClose, false);
}
void MainWindow::createActions()
{
deleteAction = new QAction(tr("&Delete Item"), this);
deleteAction->setShortcut(tr("Del"));
connect(deleteAction, SIGNAL(triggered()), this, SLOT(deleteItem()));
...
undoAction = new QAction(tr("&Undo"), this);
undoAction->setShortcut(tr("Ctrl+Z"));
undoAction->setEnabled(false);
connect(undoAction, SIGNAL(triggered()), undoStack, SLOT(undo()));
redoAction = new QAction(tr("&Redo"), this);
QList<QKeySequence> redoShortcuts;
redoShortcuts << tr("Ctrl+Y") << tr("Shift+Ctrl+Z");
redoAction->setShortcuts(redoShortcuts);
redoAction->setEnabled(false);
connect(redoAction, SIGNAL(triggered()), undoStack, SLOT(redo()));
void MainWindow::createMenus()
{
...
editMenu = menuBar()->addMenu(tr("&Edit"));
editMenu->addAction(undoAction);
editMenu->addAction(redoAction);
editMenu->addSeparator();
editMenu->addAction(deleteAction);
connect(editMenu, SIGNAL(aboutToShow()),
this, SLOT(itemMenuAboutToShow()));
connect(editMenu, SIGNAL(aboutToHide()),
this, SLOT(itemMenuAboutToHide()));
...
}
void MainWindow::itemMoved(DiagramItem *movedItem,
const QPointF &oldPosition)
{
undoStack->push(new MoveCommand(movedItem, oldPosition));
}
void MainWindow::itemMenuAboutToHide()
{
deleteAction->setEnabled(true);
}
void MainWindow::itemMenuAboutToShow()
{
undoAction->setText(tr("Undo ") + undoStack->undoText());
redoAction->setText(tr("Redo ") + undoStack->redoText());
deleteAction->setEnabled(!diagramScene->selectedItems().isEmpty());
}
void MainWindow::addBox()
{
QUndoCommand *addCommand = new AddCommand(DiagramItem::Box, diagramScene);
undoStack->push(addCommand);
}
void MainWindow::addTriangle()
{
QUndoCommand *addCommand = new AddCommand(DiagramItem::Triangle,diagramScene);
undoStack->push(addCommand);
}
void MainWindow::about()
{
QMessageBox::about(this, tr("About Undo"),
tr("The <b>Undo</b> example demonstrates how to "
"use Qt's undo framework."));
}
class AddCommand : public QUndoCommand
{
public:
AddCommand(DiagramItem::DiagramType addType, QGraphicsScene *graphicsScene,
QUndoCommand *parent = 0);
void undo();
void redo();
private:
DiagramItem *myDiagramItem;
QGraphicsScene *myGraphicsScene;
QPointF initialPosition;
};
AddCommand::AddCommand(DiagramItem::DiagramType addType,
QGraphicsScene *scene, QUndoCommand *parent)
: QUndoCommand(parent)
{
static int itemCount = 0;
myGraphicsScene = scene;
myDiagramItem = new DiagramItem(addType);
initialPosition = QPointF((itemCount * 15) % int(scene->width()),
(itemCount * 15) % int(scene->height()));
scene->update();
++itemCount;
setText(QObject::tr("Add %1")
.arg(createCommandString(myDiagramItem, initialPosition)));
}
void AddCommand::undo()
{
myGraphicsScene->removeItem(myDiagramItem);
myGraphicsScene->update();
}
class DeleteCommand : public QUndoCommand
{
public:
DeleteCommand(QGraphicsScene *graphicsScene, QUndoCommand *parent = 0);
void undo();
void redo();
private:
DiagramItem *myDiagramItem;
QGraphicsScene *myGraphicsScene;
};
DeleteCommand::DeleteCommand(QGraphicsScene *scene, QUndoCommand *parent)
: QUndoCommand(parent)
{
myGraphicsScene = scene;
QList<QGraphicsItem *> list = myGraphicsScene->selectedItems();
list.first()->setSelected(false);
myDiagramItem = static_cast<DiagramItem *>(list.first());
setText(QObject::tr("Delete %1")
.arg(createCommandString(myDiagramItem, myDiagramItem->pos())));
}
void DeleteCommand::undo()
{
myGraphicsScene->addItem(myDiagramItem);
myGraphicsScene->update();
}
void DeleteCommand::redo()
{
myGraphicsScene->removeItem(myDiagramItem);
}
class MoveCommand : public QUndoCommand
{
public:
enum { Id = 1234 };
MoveCommand(DiagramItem *diagramItem, const QPointF &oldPos,
QUndoCommand *parent = 0);
void undo();
void redo();
bool mergeWith(const QUndoCommand *command);
int id() const { return Id; }
private:
DiagramItem *myDiagramItem;
QPointF myOldPos;
QPointF newPos;
};
MoveCommand::MoveCommand(DiagramItem *diagramItem, const QPointF &oldPos,
QUndoCommand *parent)
: QUndoCommand(parent)
{
myDiagramItem = diagramItem;
newPos = diagramItem->pos();
myOldPos = oldPos;
}
void MoveCommand::undo()
{
myDiagramItem->setPos(myOldPos);
myDiagramItem->scene()->update();
setText(QObject::tr("Move %1")
.arg(createCommandString(myDiagramItem, newPos)));
}
void MoveCommand::redo()
{
myDiagramItem->setPos(newPos);
setText(QObject::tr("Move %1")
.arg(createCommandString(myDiagramItem, newPos)));
}
bool MoveCommand::mergeWith(const QUndoCommand *command)
{
const MoveCommand *moveCommand = static_cast<const MoveCommand *>(command);
DiagramItem *item = moveCommand->myDiagramItem;
if (myDiagramItem != item)
return false;
newPos = item->pos();
setText(QObject::tr("Move %1")
.arg(createCommandString(myDiagramItem, newPos)));
return true;
}
class DiagramScene : public QGraphicsScene
{
Q_OBJECT
public:
DiagramScene(QObject *parent = 0);
signals:
void itemMoved(DiagramItem *movedItem, const QPointF &movedFromPosition);
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
private:
QGraphicsItem *movingItem;
QPointF oldPos;
};
int main(int argv, char *args[])
{
Q_INIT_RESOURCE(undoframework);
QApplication app(argv, args);
MainWindow mainWindow;
mainWindow.show();
return app.exec();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -