How do I correctly remove/stop a timer in actionscript?
I do it like in this piece of code but timer has been set to fire frame1SoundTimerHandler in 200 seconds later :
playingScreenFramesObj.myTimer2.stop();
playingScreenFramesObj.myTimer2.removeEventListener(TimerEvent.TIMER, frame1SoundTimerHandler);
playingScreenFramesObj.myTimer2 = null;
It seems that despite stopping/removing the timer with the code above the handler will run in 200 seconds.
Where is the mistake I make?
Chris
You should only have to call timer.stop(). As a failsafe you could always check timer.running from inside the event handler.
That code should work. Are you positive you are calling stop on the correct timer? For example, could you accidentally be using timer1 and stopping timer2?
Related
I'm trying to implement for loop using timers. Actualy my intention is to avoid stuck in long running for loop and have smooth behaviour in my program. is this possible ? any references ?
If I unterstand what you want, you cam Implement Timer : http://help.adobe.com/fr_FR/FlashPlatform/reference/actionscript/3/flash/utils/Timer.html
use function start() to start your timer and listen the event TimerEvent.TIMER_COMPLETE.
If you want restart your timer, use reset() and start() again.
MyWindow which inherits from QMainWindow. MyWindow contains a QGLWidget that displays an animation.
The problem is that the animation pauses whenever I open a menu or resize the window.
The animation is implemented by calling QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest)) periodically, then calling redrawing each time the window receives the QEvent::UpdateRequest, like this:
bool MyWindow::event(QEvent *event)
{
qDebug() << event;
switch (event->type())
{
case QEvent::UpdateRequest:
render();
return true;
default:
return QMainWindow::event(event);
}
}
As seen from qDebug(), while a menu is open or the window is being resized, the window stops receiving update request events.
Is there a setting on QMainWindow/QWidget to make it continue to receive update request events? Or is there some better way to implement the animation?
Edit: I'm on Mac OS X.
This may be a Qt bug. I'll investigate.
Alas, you're way overcomplicating your code.
The postEvent should be simply replaced by this->update(). Behind the scenes it posts the event for you.
One can simply connect a QTimer instance's signal to widget, SLOT(update()). If you want to save on a QObject instance, use QBasicTimer and reimplement timerEvent as follows: void MyWidget::timerEvent(QTimerEvent* ev) { if (ev.timerId() == m_timer.timerId()) update(); }
There's no need to deal with event() reimplementation. Simply reimplement paintEvent() - that's what it's for.
Qt GUI updates are performing on MainThread. So slow gui response is reasonable, if you have many gui functionality does at same time. So generally, do not overload MaiThread with so many heavey function calls.
Probable solution to speed up your GUI response.
If PostEvent is called by your MainThread( if you are using timer from main gui thread ), instead move those to backend functionality in
a worker thread and postEvent once it has been done.
you call QCoreApplication::processEvents(), after your render(); function in MainThread.
This will help system to process all the other events that are in the event-loop before to continue
Please check, following link How to improve GUI response
Note: When creating and triggering the timer it will run within your thread by default, it wont start another thread.
Since I haven't heard any more from Kuba Ober about the possibility of this being a Qt bug, I went ahead and filed a bug report: https://bugreports.qt-project.org/browse/QTBUG-33382
I was able to partially work around the problem by calling the render() function more directly — that is, instead of sending an event, receiving the event, and having the event handler call the function. I accomplished this with a dispatch queue (but not the main dispatch queue, since that's tied to the default run loop so it has the same problem). However, working with the QGLWidget on multiple threads was difficult. After trying for a while to use the moveToThread() function to make this work, and considering other factors involved in the project, I decided to use something other than Qt to display this window.
i have a problem with QPropertyAnimation in Qt
my code:
QString my_text = "Hello Animation";
ui->textBrowser->setText((quote_text));
ui->textBrowser->show();
QPropertyAnimation animation2(ui->textBrowser,"geometry");
animation2.setDuration(1000);
animation2.setStartValue(QRect(10,220/4,1,1));
animation2.setEndValue(QRect(10,220,201,71));
animation2.setEasingCurve(QEasingCurve::OutBounce);
animation2.start();
till now it seems very good , but the problem is that i can see this animation only when i show a message box after it .
QMessageBox m;
m.setGeometry(QRect(100,180,100,50));
m.setText("close quote");
m.show();
m.exec();
when i remove the code of this message box , i can't see the animation anymore.
the functionality of the program doesn't require showing this MessageBox at all.
Can anybody help?
Maybe it is an update problem. Could you try to connect the valueChanged() signal of QPropertyAnimation to an update() call in the GUI?
My guess is that the code for the animation that you present is inside a larger chunk of code where the control doesn't get back to the event loop (or the event loop hasn't started yet). This means that when the MessageBox's exec function is called, an event loop starts operating again, and the animation starts. If you were to dismiss the message box in the middle of the animation, it would probably freeze at that point, as well.
animation2 is declared as a local variable. When the enclosing function
exits, it is no longer in scope and is deleted. The animation never runs as
it does not exist when Qt returns to the event loop and, as noted in the QAbstractAnimation
documentation
(QPropertyAnimation inherits QAbstractAnimation), for QPropertyAnmiation to execute, it must exist when Qt returns to the event loop.
When control reaches the event loop, the animation will run by itself,
periodically calling updateCurrentTime() as the animation progresses.
The solution is to dynamically allocate animation2 rather than declare it as
a local variable.
QPropertyAnimation *animation2 = new QPropertyAnimation(ui->textBrowser,"geometry");
animation2->setDuration(1000);
animation2->setStartValue(QRect(10,220/4,1,1));
animation2->setEndValue(QRect(10,220,201,71));
animation2->setEasingCurve(QEasingCurve::OutBounce);
animation2->start();
Note that this it the same technique is the same as that used in the C++
example provided in the QPropertyAnmiation
documentation:
QPropertyAnimation *animation = new QPropertyAnimation(myWidget, "geometry");
animation->setDuration(10000);
animation->setStartValue(QRect(0, 0, 100, 30));
animation->setEndValue(QRect(250, 250, 100, 30));
animation->start();
The original question notes:
i can see this animation only when i show a message box after it
This is an interesting side affect of how QMessageBox works. The exec()
method executes an event loop. Since the event loop executes within the scope
of the function enclosing animation2, animation2 still exists and the
desired animation executes.
By default, animation2 will be deleted when the parent, ui->textBrowser in
the original question, is deleted. If you wish for the animation to be
deleted when it completes executing, QAbstractAnimation provides a property
that controls when the animation is deleted. To automatically delete
animation2 when it finishes executing, change the start() method to:
animation2->start(QAbstractAnimation::DeleteWhenStopped);
I'm facing a practical problem with Qt. I'm using a class that communicates with QLocalSocket to another process (pipes/unix sockets) and I need to do that communication before other events occur, that is before app.exec() starts (or more precisely,as soon as app starts). The class that I'm using needs an eventloop so it does not work if I call the class methods before an event loop is started. There is any way to start something when the event loop is ready? I thought of making a hidden event-only window and do my duties in the hidden window constructor, and stablish this window as toplevel.
Basically, I need this local-socket communication task to start as soon as the event loop becomes available.
Any ideas?
Thank you.
You could start a separate eventloop, using QEventLoop, before calling QApplication::exec(). You should emit a "done" signal from your class and connect that to the QEventLoop quit() slot, or use an existing signal provided in the Qt class you're using.
Here's a simple example fetching a webpage using QNetworkAccessManager:
app = QtCore.QCoreApplication([])
manager = QtNetwork.QNetworkAccessManager()
req = QtNetwork.QNetworkRequest(QtCore.QUrl("http://www.google.com"))
resp = manager.get(req)
eventloop = QtCore.QEventLoop()
eventloop.connect(resp, QtCore.SIGNAL('finished()'), QtCore.SLOT('quit()'))
eventloop.exec_() # this will block until resp emits finished()
print resp.readAll()
app.exec_()
While this might suit your needs, I couldn't quite understand why you can't simply do whatever business you have prior to calling show() on your window, once that's done, call show().
If you just need to start the communications before everything else, you can simply use a single-shot timer with 0ms delay:
QTimer::singleShot(0, commsInstancePtr, SLOT(startCommunication()));
If you need your operations to actually finish before doing everything else, Daniel's solution might be more suitable.
Is there any way to halt execution in ActionScript, such as a sleep() method?
I know that there is a setTimeout() method, but setTimeout() just sets up an event for deferred execution.
No. There is no sleep. Sorry.
See my answer here for options: ActionScript: pushing a closure onto the event stack?. It doesn't talk about sleeping, but I tried to provide an overview of deferred function calling.
You need to think in terms of not sleeping. Actionscript is not that kind of language. Because the flash player alternates between frame renders and code execution, sleeping in the code is always a bad idea, which is why there is no method to do it.
Having said that, you could achieve this by using the blocking method ExternalInterface.call, and in Javascript executing a blocking method (like XHR request).
Absolutely idiotic though, so don't do it.
Perhaps what you need is a Timer.
There's no way to pause all execution of an application as in PHP, but there are workarounds (unless you set a breakpoint or create a runtime error on purpose, don't think that's what you meant). Probably this is because usually flash applications are meant to execute all the scripts in less than one "frame".
It's common to be able to "pause" the animations of a website when the user unfocus it. This can be made by listening to Event.DEACTIVATE and then remove the ENTER_FRAME listeners and kill all ongoing processes.
You could also create a central EventDispatcher to replace the internal ENTER_FRAME, this way you seamlessly control speed of execution as well as pausing / resuming (won't stop executing scripts, nor asynchronous handlers such as loaders etc. though).
Yes, there is, though be aware of the 15 second script timeout. ( You can change that 15 second script timeout in the Publish Settings... )
I've found in the past that if you're looking for this functionality, you're doing something wrong :)
Whatever you're trying to accomplish is probably calling for an Event listener instead.
//adding this ENTER_FRAME event listener just to show that the script pauses for one
// second before the first frame executes
addEventListener( Event.ENTER_FRAME, onFrame );
function onFrame( event:Event ):void {
trace( "first frame occurs after pause of", getTimer() + " ms" );
removeEventListener( Event.ENTER_FRAME, onFrame );
};
var startTime:int = getTimer();
var pauseTime:int = 1000;
while( ( getTimer() - startTime ) < pauseTime ) {
//do nothing... we're effectively pausing here...
}