Qt-状态机
//以下示例是QT示例中的appchooser例子,使用状态机来进行图标的交互. #include <QtCore> #include <QtWidgets> class Pixmap : public QGraphicsWidget { Q_OBJECT public: Pixmap(const QPixmap &pix, QGraphicsItem *parent = 0) : QGraphicsWidget(parent), orig(pix), p(pix) { } void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override { painter->drawPixmap(QPointF(), p); } void mousePressEvent(QGraphicsSceneMouseEvent *) override { emit clicked(); } void setGeometry(const QRectF &rect) override { QGraphicsWidget::setGeometry(rect); if (rect.size().width() > orig.size().width()) p = orig.scaled(rect.size().toSize()); else p = orig; } Q_SIGNALS: void clicked(); private: QPixmap orig; QPixmap p; }; class GraphicsView : public QGraphicsView { Q_OBJECT public: GraphicsView(QGraphicsScene *scene, QWidget *parent = 0) : QGraphicsView(scene, parent) { } void resizeEvent(QResizeEvent *) override { fitInView(sceneRect(), Qt::KeepAspectRatio); } }; void createStates(const QObjectList &objects, const QRect &selectedRect, QState *parent) { for (int i = 0; i < objects.size(); ++i) { QState *state = new QState(parent); state->assignProperty(objects.at(i), "geometry", selectedRect); //设置状态的属性 parent->addTransition(objects.at(i), SIGNAL(clicked()), state); //状态业务添加至父状态组中 } } void createAnimations(const QObjectList &objects, QStateMachine *machine) { for (int i=0; i<objects.size(); ++i) machine->addDefaultAnimation(new QPropertyAnimation(objects.at(i), "geometry")); //设置动画 } int main(int argc, char **argv) { Q_INIT_RESOURCE(appchooser); QApplication app(argc, argv); Pixmap *p1 = new Pixmap(QPixmap(":/digikam.png")); Pixmap *p2 = new Pixmap(QPixmap(":/akregator.png")); Pixmap *p3 = new Pixmap(QPixmap(":/accessories-dictionary.png")); Pixmap *p4 = new Pixmap(QPixmap(":/k3b.png")); p1->setObjectName("p1"); p2->setObjectName("p2"); p3->setObjectName("p3"); p4->setObjectName("p4"); p1->setGeometry(QRectF( 0.0, 0.0, 64.0, 64.0)); p2->setGeometry(QRectF(236.0, 0.0, 64.0, 64.0)); p3->setGeometry(QRectF(236.0, 236.0, 64.0, 64.0)); p4->setGeometry(QRectF( 0.0, 236.0, 64.0, 64.0)); QGraphicsScene scene(0, 0, 300, 300); scene.setBackgroundBrush(Qt::white); scene.addItem(p1); scene.addItem(p2); scene.addItem(p3); scene.addItem(p4); GraphicsView window(&scene); window.setFrameStyle(0); window.setAlignment(Qt::AlignLeft | Qt::AlignTop); window.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); window.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); QStateMachine machine; machine.setGlobalRestorePolicy(QState::RestoreProperties); //设置状态机复原策略,当有新的状态来时,自动复原旧状态的初始值. QState *group = new QState(&machine); group->setObjectName("group"); QRect selectedRect(86, 86, 128, 128); QState *idleState = new QState(group); group->setInitialState(idleState); //设置空状态为group状态组的初始状态 QObjectList objects; objects << p1 << p2 << p3 << p4; createStates(objects, selectedRect, group); createAnimations(objects, &machine); machine.setInitialState(group); //设置状态机的初始状态,状态机必须设置初始状态才能start(). machine.start(); window.resize(300, 300); window.show(); return app.exec(); } #include "main.moc" //以下是QT帮助文档中关于QStateMachine的用法的节选. 退出状态机就是Enter顶层的QFinalState.或者显示的调用stop(). //The state machine processes events and takes transitions until a top-level QFinalState is entered; //the state machine then emits the finished() signal. You can also stop() the state machine explicitly. //The stopped() signal is emitted in this case. //The following snippet shows a state machine that will finish when a button is clicked: QPushButton button; QStateMachine machine; QState *s1 = new QState(); s1->assignProperty(&button, "text", "Click me"); QFinalState *s2 = new QFinalState(); s1->addTransition(&button, SIGNAL(clicked()), s2); machine.addState(s1); machine.addState(s2); machine.setInitialState(s1); machine.start();