状态范例

The States example shows how to use the Qt state machine to play animations.

The example demonstrates how QStateMachine states can be used to animate properties of widgets. There are three states in the application that can be sequentially triggered by a button. The button initiates state transitions that animate the properties of the application widgets.

main() 函数

int main(int argc, char *argv[])
{
    Q_INIT_RESOURCE(states);
    QApplication app(argc, argv);
    // Text edit and button
    QTextEdit *edit = new QTextEdit;
    edit->setText("asdf lkjha yuoiqwe asd iuaysd u iasyd uiy "
                  "asdf lkjha yuoiqwe asd iuaysd u iasyd uiy "
                  "asdf lkjha yuoiqwe asd iuaysd u iasyd uiy "
                  "asdf lkjha yuoiqwe asd iuaysd u iasyd uiy!");
    QPushButton *button = new QPushButton;
    QGraphicsProxyWidget *buttonProxy = new QGraphicsProxyWidget;
    buttonProxy->setWidget(button);
    QGraphicsProxyWidget *editProxy = new QGraphicsProxyWidget;
    editProxy->setWidget(edit);
    QGroupBox *box = new QGroupBox;
    box->setFlat(true);
    box->setTitle("Options");
    QVBoxLayout *layout2 = new QVBoxLayout;
    box->setLayout(layout2);
    layout2->addWidget(new QRadioButton("Herring"));
    layout2->addWidget(new QRadioButton("Blue Parrot"));
    layout2->addWidget(new QRadioButton("Petunias"));
    layout2->addStretch();
    QGraphicsProxyWidget *boxProxy = new QGraphicsProxyWidget;
    boxProxy->setWidget(box);
    // Parent widget
    QGraphicsWidget *widget = new QGraphicsWidget;
    QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical, widget);
    layout->addItem(editProxy);
    layout->addItem(buttonProxy);
    widget->setLayout(layout);
    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"));
    Pixmap *p5 = new Pixmap(QPixmap(":/help-browser.png"));
    Pixmap *p6 = new Pixmap(QPixmap(":/kchart.png"));
    QGraphicsScene scene(0, 0, 400, 300);
    scene.setBackgroundBrush(scene.palette().window());
    scene.addItem(widget);
    scene.addItem(boxProxy);
    scene.addItem(p1);
    scene.addItem(p2);
    scene.addItem(p3);
    scene.addItem(p4);
    scene.addItem(p5);
    scene.addItem(p6);
					

The widgets are created and added to the QGraphicsScene . The Pixmap class is also defined in the example. It extends QGraphicsPixmapItem so that its position can be read and written as Qt properties.

    QStateMachine machine;
    QState *state1 = new QState(&machine);
    QState *state2 = new QState(&machine);
    QState *state3 = new QState(&machine);
    machine.setInitialState(state1);
					

The state machine and the states are created.

    // State 1
    state1->assignProperty(button, "text", "Switch to state 2");
    state1->assignProperty(widget, "geometry", QRectF(0, 0, 400, 150));
    state1->assignProperty(box, "geometry", QRect(-200, 150, 200, 150));
    state1->assignProperty(p1, "pos", QPointF(68, 200)); // 185));
    state1->assignProperty(p2, "pos", QPointF(168, 200)); // 185));
    state1->assignProperty(p3, "pos", QPointF(268, 200)); // 185));
    state1->assignProperty(p4, "pos", QPointF(68 - 150, 48 - 150));
    state1->assignProperty(p5, "pos", QPointF(168, 48 - 150));
    state1->assignProperty(p6, "pos", QPointF(268 + 150, 48 - 150));
    state1->assignProperty(p1, "rotation", qreal(0));
    state1->assignProperty(p2, "rotation", qreal(0));
    state1->assignProperty(p3, "rotation", qreal(0));
    state1->assignProperty(p4, "rotation", qreal(-270));
    state1->assignProperty(p5, "rotation", qreal(-90));
    state1->assignProperty(p6, "rotation", qreal(270));
    state1->assignProperty(boxProxy, "opacity", qreal(0));
    state1->assignProperty(p1, "opacity", qreal(1));
    state1->assignProperty(p2, "opacity", qreal(1));
    state1->assignProperty(p3, "opacity", qreal(1));
    state1->assignProperty(p4, "opacity", qreal(0));
    state1->assignProperty(p5, "opacity", qreal(0));
    state1->assignProperty(p6, "opacity", qreal(0));
					

Each state is assigned the object properties that they will apply.

    QAbstractTransition *t1 = state1->addTransition(button, &QAbstractButton::clicked, state2);
    QSequentialAnimationGroup *animation1SubGroup = new QSequentialAnimationGroup;
    animation1SubGroup->addPause(250);
    animation1SubGroup->addAnimation(new QPropertyAnimation(box, "geometry"));
    t1->addAnimation(animation1SubGroup);
    t1->addAnimation(new QPropertyAnimation(widget, "geometry"));
    t1->addAnimation(new QPropertyAnimation(p1, "pos"));
    t1->addAnimation(new QPropertyAnimation(p2, "pos"));
    t1->addAnimation(new QPropertyAnimation(p3, "pos"));
    t1->addAnimation(new QPropertyAnimation(p4, "pos"));
    t1->addAnimation(new QPropertyAnimation(p5, "pos"));
    t1->addAnimation(new QPropertyAnimation(p6, "pos"));
    t1->addAnimation(new QPropertyAnimation(p1, "rotation"));
    t1->addAnimation(new QPropertyAnimation(p2, "rotation"));
    t1->addAnimation(new QPropertyAnimation(p3, "rotation"));
    t1->addAnimation(new QPropertyAnimation(p4, "rotation"));
    t1->addAnimation(new QPropertyAnimation(p5, "rotation"));
    t1->addAnimation(new QPropertyAnimation(p6, "rotation"));
    t1->addAnimation(new QPropertyAnimation(p1, "opacity"));
    t1->addAnimation(new QPropertyAnimation(p2, "opacity"));
    t1->addAnimation(new QPropertyAnimation(p3, "opacity"));
    t1->addAnimation(new QPropertyAnimation(p4, "opacity"));
    t1->addAnimation(new QPropertyAnimation(p5, "opacity"));
    t1->addAnimation(new QPropertyAnimation(p6, "opacity"));
					

The state transitions are created with the trigger of the button click. For each property, a QPropertyAnimation is created that interpolates between the property values.

    machine.start();
    GraphicsView view(&scene);
    view.show();
    return app.exec();
					

The state machine is started and the scene is assigned to a GraphicsView.

范例工程 @ code.qt.io