2017-03-08 27 views
1

我想用QStateMachine创建一个无限循环,其中我还需要动画。带动画的QStateMachine事件循环

QColor leastTransparent, mostTransparent = color(); 
leastTransparent.setAlpha(250); 
mostTransparent.setAlpha(150); 

QState *s1 = new QState(); 
s1->assignProperty(this, "color", leastTransparent); 

QState *s2 = new QState(); 
s2->assignProperty(this, "color", mostTransparent); 

QSignalTransition *transition = s1->addTransition(this, SIGNAL(triggerSignal()),s2); 
QSignalTransition *transition2 = s2->addTransition(s2, SIGNAL(entered),s1); 

QPropertyAnimation* animation = new QPropertyAnimation(this, "color"); 
animation->setDuration(5000); 
transition->addAnimation(animation); 

QPropertyAnimation* animation2 = new QPropertyAnimation(this, "color"); 
animation2->setDuration(10000); 
transition2->addAnimation(animation2); 

m_stateMachineAnimation->addState(s1); 
m_stateMachineAnimation->addState(s2); 
m_stateMachineAnimation->setInitialState(s1); 
m_stateMachineAnimation->setGlobalRestorePolicy(QStateMachine::RestoreProperties); 
m_stateMachineAnimation->start(); 

我期望的是在“triggerSignal”之后的第一个5秒钟,颜色会变得更加不透明。国家将是“s2”。并且比“s2”的输入信号被触发,并且它将在10秒内变得越来越透明。

但是,相反,我正在s2触发器立即没有等待5秒后立即“触发信号”,并立即s1再次触发不等待10秒。

为什么我的持续时间不被QStateMachine考虑在内。我如何用QStateMachine实现这样的动画

+0

你可以发布[S.S.C.C.E.](http://www.sscce.org/)吗? –

回答

2

您似乎期望动画创建某种中间状态。它没有这样的事情。过渡只会触发动画。您立即从s2过渡到s1,没有时间让动画完成。相反,当设置属性的最终值时,您需要显式触发后续转换。 QState::propertiesAssigned信号对此目的最有用。或者,您可以使用动画的finished()信号。

在下面的例子中,在窗口中点击开始动画循环:

// https://github.com/KubaO/stackoverflown/tree/master/questions/statemachine-animation-42682462 
#include <QtWidgets> 

const char kColor[] = "color"; 
class Widget : public QWidget { 
    Q_OBJECT 
    Q_PROPERTY(QColor color MEMBER m_color NOTIFY colorChanged) 
    QColor m_color{Qt::blue}; 
    QStateMachine m_machine{this}; 
    QState s0{&m_machine}, s1{&m_machine}, s2{&m_machine}; 
    QEventTransition t01{this, QEvent::MouseButtonPress}; 
    QPropertyAnimation anim_s1{this, kColor}, anim_s2{this, kColor}; 
    void paintEvent(QPaintEvent *) override { 
     QPainter{this}.fillRect(rect(), m_color); 
    } 
    Q_SIGNAL void colorChanged(const QColor &); 
public: 
    Widget() { 
     connect(this, &Widget::colorChanged, [this]{ update(); }); 
     s1.assignProperty(this, kColor, QColor{Qt::red}); 
     s2.assignProperty(this, kColor, QColor{Qt::green}); 

     t01.setTargetState(&s1); 
     s0.addTransition(&t01);        t01.addAnimation(&anim_s1); 
     s1.addTransition(&s1, &QState::propertiesAssigned, &s2)->addAnimation(&anim_s2); 
     s2.addTransition(&s2, &QState::propertiesAssigned, &s1)->addAnimation(&anim_s1); 

     anim_s1.setDuration(1000); 
     anim_s2.setDuration(2000); 

     m_machine.setInitialState(&s0); 
     m_machine.start(); 
    } 
}; 

int main(int argc, char ** argv) { 
    QApplication app{argc, argv}; 
    Widget w; 
    w.setFixedSize(300, 200); 
    w.show(); 
    return app.exec(); 
} 
#include "main.moc" 

顺便说一句,这证明了动画插值RGB值,造成颜色变黑redblue作为之间值从(1,0,0)(.5,.5,0)(0,1,0)。对于人类消费来说,插入HSV会更有意义,因此值(亮度)保持不变,只有色调(我们人们称之为“色彩”)才会发生变化。

+0

你节省了我的一天。 –