QT状态机

首先吐槽下网上各种博主不清不楚的讲解 特别容易让新手迷惑

总体思想是这样的:首先要有一个状态机对象, 顾名思义,这玩意就是用来容纳状态的。然后调用状态机的start()函数它就会更具你的逻辑去执行相关状态

下面看代码,精华在注释

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QGraphicsScene>
#include<QGraphicsView>
#include<QGraphicsWidget>
#include<QState>
#include<QStateMachine>
#include"MyPix.h"
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    this->setGeometry(100,100,400,400);
    QGraphicsView *view=new QGraphicsView(this);
    view->setGeometry(0,0,400,400);
    QGraphicsScene *scene=new QGraphicsScene;
    scene->setSceneRect(-200,-200,400,400);
    view->setScene(scene);
    //item scene 这些位置锚点都在其正中心
    //测试的时候注意要注意每个item本身坐标的体系的创建 否则很难看到效果
    QPixmap pix("1.png");
    MyPix *mypix=new MyPix(pix);
    scene->addItem(mypix);
    mypix->setPos(0,0);
QStateMachine
*states=new QStateMachine; QState *sm=new QState(states); QState *state1=new QState(states); #if 1 for(int i=0;i<10;i++){ //将mypix这个item添加到到state1这个状态里来 第一种效果 state1->assignProperty(mypix, "pos", QPointF(-200+i*40, -200+i*40)); } sm->addTransition(mypix,SIGNAL(pressed()),state1); //某一状态触发后 就从sm状态转换到state1状态 然而state1状态包含了Item的状态 故item状态变化 //因为状态state1只添加了item这个状态 所以一个循环执行完 实际上<==>state1->assignProperty(mypix,"pos",QPointF( //200,200)); //我们看下下面的表达方式 第二种效果 # else QList<MyPix*>pixs; for(int i=0;i<10;i++){ MyPix *mypix2=new MyPix(pix); pixs.append(mypix2); scene->addItem(mypix2); //这里的不只一个item的状态添加到了state这个状态里 state1->assignProperty(pixs.at(i), "pos", QPointF(-200+i*40, -200+i*40)); } sm->addTransition(pixs.at(9),SIGNAL(pressed()),state1); #endif states->setInitialState(sm); states->start(); } MainWindow::~MainWindow() { delete ui; }
 
//这是第item的构建方法 因为本身QGraphicsItem 不支持Q_OBJECT 这意味着信号槽不能用 所以从QGraphicsWidget自行派生定义item是最佳选择 网上也有人从QObjecth和graphicsi
//item派生的 不建议那么干

#ifndef MYPIX_H #define MYPIX_H #include<QGraphicsWidget> #include<QPixmap> class MyPix : public QGraphicsWidget { Q_OBJECT public: MyPix(QPixmap &pix); //提供在约定的范围内进行绘图等操作接口 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); //提供整个item画图操作的约定范围接口 当然这是一个君子约定 QRectF boundingRect() const; //提供一个item绘画shape接口 QPainterPath shape() const; void mousePressEvent(QGraphicsSceneMouseEvent *event); private: QPixmap _pix; signals: void pressed(); }; #endif // MYPIX_H
#include "MyPix.h"
#include<QPainter>
#include<QPainterPath>
#include<QGraphicsSceneMouseEvent>
MyPix::MyPix(QPixmap &pix):_pix(pix)
{

}
QPainterPath MyPix::shape() const
{
    QPainterPath path;
    path.addEllipse(boundingRect());
    return path;
}
void MyPix::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *){
    QRectF  p=boundingRect();
    painter->drawEllipse(p);
    painter->drawPixmap(-_pix.width()/2,-_pix.height()/2,_pix);

}
QRectF MyPix::boundingRect() const{

    return QRectF(-100,-100,200,200);
}
void MyPix::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    if(event->button()==Qt::LeftButton){

        emit pressed();
    }
}
 
第一种情况点击一下运行效果为:从中间到右下角

第二种点击一下运行效果:


原文地址:https://www.cnblogs.com/enjoyall/p/5436539.html