2017-03-08 54 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

你節省了我的一天。 –