布局中的 Qt 状态机转换

Posted

技术标签:

【中文标题】布局中的 Qt 状态机转换【英文标题】:Qt State Machine Transition in a Layout 【发布时间】:2013-09-17 21:53:45 【问题描述】:

嗯,我正在开发一个 Qt 应用程序,我想使用 Qt State Framework 来制作一些动画。

第一: 如何通过使用状态转换将水平布局中包含的一组按钮动画化为另一个垂直布局?

第二: 处于状态时如何显示小部件?例如一个菜单:当用户点击菜单中的一个按钮时,这个小部件(之前被widget->hide()隐藏的)就会显示出来...???

这是一个代码示例:

boxInsert = new BoxInsert(this);
boxInsert->hide ();


btn1 = new QPushButton("Introducir", this);
btn2 = new QPushButton("Informe", this);
btn3 = new QPushButton("Salir", this);

QStateMachine *machine = new QStateMachine(this);

QState *st1 = new QState(machine);
st1->setObjectName ("menuMode");
st1->assignProperty (btn1, "pos", QPointF(center - btn1->width () / 2, 20));
st1->assignProperty (btn2, "pos", QPointF(center - btn1->width () / 2, 40));
st1->assignProperty (btn3, "pos", QPointF(center - btn1->width () / 2, 60));
st1->assignProperty (boxInsert, "visible", QVariant(false));

QState *st2 = new QState(machine);
st2->setObjectName ("barMode");
st2->assignProperty (btn1, "pos", QPointF(40, 0));
st2->assignProperty (btn2, "pos", QPointF(40, 0));
st2->assignProperty (btn3, "pos", QPointF(40, 0));
st1->assignProperty (boxInsert, "visible", QVariant(true));

machine->setInitialState (st1);

QAbstractTransition *t1 = st1->addTransition (btn1, SIGNAL(clicked()), st2);
//QSequentialAnimationGroup *sq1 = new QSequentialAnimationGroup;
//sq1->addPause (250);
t1->addAnimation (new QPropertyAnimation(btn1, "pos"));
t1->addAnimation (new QPropertyAnimation(btn2, "pos"));
t1->addAnimation (new QPropertyAnimation(btn3, "pos"));
t1->addAnimation (new QPropertyAnimation(boxInsert, "visible"));

machine->start ();

【问题讨论】:

动画流体 GUI 是 QML 的发明,您可能想尝试一下 为一组按钮设置动画是什么意思,它们应该改变颜色吗? 【参考方案1】:

就像当你启动机器时,它会改变一个按钮的颜色,这可能表明它被点击,然后执行与你的信号相关联的操作,这样它的链接槽就会被执行。

s0->addTransition(s1);
s1->assignProperty(ui->pushButton,"styleSheet","background-color:rgb(255,0,0);");
s1->addTransition(s2);
s2->addTransition(ui->pushButton,SIGNAL(clicked()),s0);
QStateMachine m;
m.addState(s0);
m.addState(s1);
m.addState(s2);
m.setInitialState(s0);

要使小部件可见,请添加如下状态转换:

s1->assignProperty(MyWid,"visible", true);

并在 s0 中为状态 s1 添加转换。

【讨论】:

【参考方案2】:

第一: 使用 stateMachine 将小部件从水平布局移动到垂直布局?真的不知道该怎么做。

第二:您可以使用自己的透明度属性实现小部件,该属性适用于 QGraphicsEffect:

class myWidget

    //your methods
    Q_PROPERTY(double alpha READ alpha WRITE setAlpha)
    double mAlpha;
    double alpha() return mAlpha;
    void setAlpha(double a);
    QGraphicsOpacityEffect* eff;

使 QGraphicsEffect 在 setAlpha() 方法中工作:

void myWidget::setAlpha(double a)

    mAlpha = a;
    if(mAlpha < 0.0)
        mAlpha = 0.0;
    if(mAlpha > 1.0)
        mAlpha = 1.0;

    if(mAlpha == 0)
    
        this->hide();
    
    else
    
        this->show();
        eff->setOpacity(mAlpha);
    

    this->update();

当然,在构造函数中将 QGraphicsOpacityEffect 设置为您的小部件:

eff = new QGraphicsOpacityEffect(this);
eff->setOpacity(mAlpha);
this->setGraphicsEffect(eff);

然后您可以在 QState 中使用您的 alpha 属性:

QState* s1 = new QState(mainState);
s1->assignProperty(mywidget, "alpha", 1.0);
//and so on...

【讨论】:

以上是关于布局中的 Qt 状态机转换的主要内容,如果未能解决你的问题,请参考以下文章

一款用于绘制状态机转换图和流程图的web在线绘图工具

python Python中的基本状态机实现,使用namedtuples作为状态和函数作为转换

简述游戏开发中的状态机

有限状态机FSM详解及其实现

使用C ++数据模型与Qt SCXML状态机

Unity中的有限状态机FSM