2017-03-08 19 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秒間ますます透明になります。

代わりに、私は "triggerSignal"の直後に5秒待ってすぐにs2を起動し、すぐにs1が10秒間待たずに再び起動されるようにしています。

なぜQStateMachineでは時間が考慮されません。 QStateMachineでこのようなアニメーションを実現するにはどうすればいいですか?

+0

あなたは[S.S.C.C.E.](http://www.sscce.org/)を投稿できますか? –

答えて

2

アニメーションが何らかの中間の状態を作り出すと思われるようです。そんなことはありません。トランジションは単にアニメーションをトリガします。 s2からs1にすぐに移行するので、アニメーションが終了する時間がありません。代わりに、プロパティの最終値が設定されたときに、後続の遷移を明示的にトリガする必要があります。 QState::propertiesAssignedシグナルは、この目的に最も有用です。また、アニメーションのfinished()シグナルを使用することもできます。以下の例で

、アニメーションループを開始するためにウィンドウ内でクリックしてください。さておき、これはredblueなどの間消灯する色を引き起こし、アニメーションはRGB値を補間することを実証するよう

// 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" 

を値は(1,0,0)から(.5,.5,0)から(0,1,0)になります。人間が消費するためには、HSVを補間するほうが意味があり、その値(明るさ)は変わらず、色相(人間が実際に「色」と呼ぶもの)だけが変化します。

+0

あなたは私の一日を救った。 –

関連する問題