Animate buttons
-
Hello,
I would like to animate my 4 QPushButton so when I click on button1 the state1 will be trigger, when I click on button2 this trigger state2 and the click on button3 trigger state3.I tried and tried to do this but unsuccessful :(
my code is based on this Qt example: "http://doc.trolltech.com/4.7/animation-moveblocks.html":http://doc.trolltech.com/4.7/animation-moveblocks.html
please help me to do this and if possible simplify me the code if it's simplifiable because I don't need the random state triggering as in the above Qt example
main.cpp
@#include <QtCore>
#include <QtGui>class StateSwitchEvent: public QEvent
{
public:StateSwitchEvent(int rand): QEvent(Type(StateSwitchType)), m_rand(rand) { } enum { StateSwitchType = QEvent::User + 256 }; int rand() const { return m_rand; }
private:
int m_rand;
};class StateSwitchTransition: public QAbstractTransition
{
public:
StateSwitchTransition(int rand): QAbstractTransition(), m_rand(rand)
{
}protected:
virtual bool eventTest(QEvent *event)
{
return (event->type() == QEvent::Type(StateSwitchEvent::StateSwitchType))
&& (static_cast<StateSwitchEvent *>(event)->rand() == m_rand);
}virtual void onTransition(QEvent *) {}
private:
int m_rand;
};class StateSwitcher : public QState
{
Q_OBJECT
public:
StateSwitcher(QStateMachine *machine): QState(machine), m_stateCount(0), m_lastIndex(0)
{ }virtual void onEntry(QEvent *) { int n; while ((n = (qrand() % m_stateCount + 1)) == m_lastIndex) { } m_lastIndex = n; machine()->postEvent(new StateSwitchEvent(n)); } virtual void onExit(QEvent *) {} void addState(QState *state, QAbstractAnimation *animation) { StateSwitchTransition *trans = new StateSwitchTransition(++m_stateCount); trans->setTargetState(state); addTransition(trans); trans->addAnimation(animation); }
private:
int m_stateCount;
int m_lastIndex;
};QState *createGeometryState(QObject *w1, const QRect &rect1,
QObject *w2, const QRect &rect2,
QObject *w3, const QRect &rect3,
QObject *w4, const QRect &rect4,
QState *parent)
{
QState *result = new QState(parent);
result->assignProperty(w1, "geometry", rect1);
result->assignProperty(w2, "geometry", rect2);
result->assignProperty(w3, "geometry", rect3);
result->assignProperty(w4, "geometry", rect4);return result;
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);QWidget window; QPalette palette; palette.setBrush(QPalette::Window, Qt::black); window.setPalette(palette); QPushButton *button1 = new QPushButton("A", &window); QPushButton *button2 = new QPushButton("B", &window); QPushButton *button3 = new QPushButton("C", &window); QPushButton *button4 = new QPushButton("D", &window); QStateMachine machine; QState *group = new QState(); QTimer timer;
// timer.setInterval(2000);
// timer.setSingleShot(true);
// QObject::connect(group, SIGNAL(entered()), &timer, SLOT(start()));QState *state1; QState *state2; QState *state3; state1 = createGeometryState(button1, QRect(8, 5, 50, 50), button2, QRect(66, 5, 50, 50), button3, QRect(124, 5, 50, 50), button4, QRect(182, 5, 50, 50), group); state2 = createGeometryState(button1, QRect(8, 200, 50, 50), button2, QRect(66, 200, 50, 50), button3, QRect(124, 200, 50, 50), button4, QRect(182, 200, 50, 50), group); state3 = createGeometryState(button1, QRect(150, 100, 50, 50), button2, QRect(100, 100, 50, 50), button3, QRect(50, 100, 50, 50), button4, QRect(0, 100, 50, 50), group); group->setInitialState(state1); QParallelAnimationGroup animationGroup; QSequentialAnimationGroup *subGroup; QPropertyAnimation *anim = new QPropertyAnimation(button4, "geometry"); anim->setDuration(4000); anim->setEasingCurve(QEasingCurve::OutElastic); animationGroup.addAnimation(anim); subGroup = new QSequentialAnimationGroup(&animationGroup); subGroup->addPause(100); anim = new QPropertyAnimation(button3, "geometry"); anim->setDuration(4000); anim->setEasingCurve(QEasingCurve::OutElastic); subGroup->addAnimation(anim); subGroup = new QSequentialAnimationGroup(&animationGroup); subGroup->addPause(150); anim = new QPropertyAnimation(button2, "geometry"); anim->setDuration(4000); anim->setEasingCurve(QEasingCurve::OutElastic); subGroup->addAnimation(anim); subGroup = new QSequentialAnimationGroup(&animationGroup); subGroup->addPause(200); anim = new QPropertyAnimation(button1, "geometry"); anim->setDuration(4000); anim->setEasingCurve(QEasingCurve::OutElastic); subGroup->addAnimation(anim); StateSwitcher *stateSwitcher = new StateSwitcher(&machine); group->addTransition(&timer, SIGNAL(timeout()), stateSwitcher); stateSwitcher->addState(state1, &animationGroup); stateSwitcher->addState(state2, &animationGroup); stateSwitcher->addState(state3, &animationGroup); //QObject::connect(button1, SIGNAL(clicked()), &group, SLOT(stateSwitcher)); //I tried to connect button1 but unsuccessful and I don't know how connect it to state1 machine.addState(group); machine.setInitialState(group); machine.start(); window.resize(250, 250); window.show(); return app.exec();
}
#include "main.moc"@
thank you for your hep
-
If I understand your question correctly it may be simpler to connect the button click event to a state machine that makes the transition from one state to the other. Depending on which button was pressed, a different transition could be chosen in the connect.
That is assuming you want to go to the new state regardless of the order the buttons were clicked and regardless of the previous state.
If you want to change states in some predictable order you must always enter the state machine with the same transition and carry forward the destination state before exit.
From your description it seems more straightforward to start animation state machines (separate ones for each of the selected buttons) to do the animation and just use conventional signal/slot mechanics for the button clicks.