Beginner SIGNALS and SLOTS question



  • Probably very silly question but I cannot figure it out.

    In a window class I have this:

    @//Create, connect, and start the animation timer
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()),animationClass,SLOT(animate()));
    timer->start(1000);@

    and in animationCLass I have this:
    @
    void animationClass::animate(){

    //Various things from several other classes are animated here
    }@

    When certain events take place within the animate() function I want the whole animation to stop.

    How do I do that?



  • What is animationClass?
    If is derived from QAbstractAnimation then use
    @QAbstractAnimation::stop () [slot]@



  • Does it mean you want to stop the timer, when that event has occurred?

    Is your Animation class in control of the time? If so, simply let it call QTimer::stop() then.

    If the QTimer is "outside" the animation class and the animation class has no way to stop it directly, let your animation class a signal, like, stopConditionEncountered(). Then, whichever class/object is in control of the timer can react on that signal - and stop the timer.



  • AnimationClass is a QWidget

    @class Screen : public QWidget@

    The connect function is in a Window class which takes the a Screen object as a parameter

    @Window w(screen);@

    I tried calling stop() from inside the animate() function but I have no access to the timer there.
    I also tried disconnect() but it didn't seem to do anything.



  • Then I'd suggest to emit a signal, as suggested above.

    Either that, or consider moving the QTimer into your Animation class/object.



  • This is much easier in QML, if you bind your animation to a bool value, it will interrupt as soon as it is false.



  • bq. If the QTimer is “outside” the animation class and the animation class has no way to stop it directly, let your animation class a signal, like, stopConditionEncountered(). Then, whichever class/object is in control of the timer can react on that signal – and stop the timer.

    Ok that would be awesome but I have absolutely no idea how to do that. I there somewhere that explains how to do something like that?

    DO I have to set up a whole new SIGNAL and SLOT connection heading the other way (from the widget to the window) os can I just signal the connect to stop from inside the widget?



  • bq. This is much easier in QML, if you bind your animation to a bool value, it will interrupt as soon as it is false.

    Unfortunately I am stuck with someone else's implementation and I cannot change it very much.



    1. You add a signal to your Animation class
    2. You add a corresponding slot to the class that has the QTimer
    3. You connect that signal to the slot (and yes, it's a separate connection)
    4. You make Animation class/object emit the signal at the right time
    5. You make the other class/object stop the timer in the slot function

    --

    See also:
    http://qt-project.org/doc/qt-4.8/signalsandslots.html



  • Alternative approach:

    In the constructor of the Animation class, you pass a pointer to your QTimer, so the Animation class can connect itself to that timer. This has the advantage that the Animation class can also store that pointer to the QTimer in a member variable for stopping the QTimer later (directly!).

    Though this approach has some drawbacks too: If the QTimer gets destroyed "outside" of Animation class you have a dangling pointer. Also, when Animation class decides to stop the QTimer, other classes listening to that same timer are effected too. And they have no chance to prevent Animation class from stopping the timer.



  • Create the QTimer as a SingleShot. After the timeout() it will stop, until you start it again. Create a signal in the Widget which will be fired as soon as the animation is done. Use that signal to start the timer again.



  • I am a little confused here.

    In either case you suggest MuldeR I need at least a reference to the class I want to signal and/or get a pointer to it's timer don't I?

    Since the Window is already taking the Screen:QWidget as a parameter, I can't pass a reference to the Window - or any of it's member variables - as they don't exist yet.

    I do like the second Idea, just not sure how to pull it off.



  • If you connect signals/slots of two objects, you always need references to these objects - at that point. Though, the objects that get connected don't need to know of each other. In the first approach I suggested, Animation class doesn't need a reference to QTimer. It doesn't even know that QTimer exists. It just emits a timeToStopNow() signal when it wants to stop and that's it.



  • bq. In the constructor of the Animation class, you pass a pointer to your QTimer, so the Animation class can connect itself to that timer. This has the advantage that the Animation class can also store that pointer to the QTimer in a member variable for stopping the QTimer later (directly!).
    Though this approach has some drawbacks too: If the QTimer gets destroyed “outside” of Animation class you have a dangling pointer. Also, when Animation class decides to stop the QTimer, other classes listening to that same timer are effected too. And they have no chance to prevent Animation class from stopping the timer.

    Wow ok I am an idiot, I just had to pass the timer as a parameter to the Window and the Widget ><

    Then I could call stop() as your alternative method suggested.

    I don't think it's ideal, but I have no others classes listening to the SIGNAL.



  • Example:

    @OuterClass::foo()
    {
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()),animationClass,SLOT(animate()));
    connect(animationClass, SIGNAL(timeToStopNow()),this,SLOT(bar()));
    timer->start(1000);
    }

    OuterClass::bar()
    {
    timer->stop();
    }@

    Assuming "timer" is a member variable of OuterClass.



  • Ah I see, I misunderstood the documentation about signals.

    The help has all been excellent by the way, thank you.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.