Set Delay Timer
-
Hi
I make a Programm using C++ and Netbeans with a lot of pushbuttonI would like to do something like this
When i click the button, it should change to the Position i want and Change the border style or maybe Background to red or whatever and after maybe 300ms it should Change back to normal
The part with changing Position worked for me.I used to Google but I didn found any solution. I try something like this but itsnot work
void Game::buttonClicked(QWidget* _button){ // Clicked button identifire with QSignalMapper QPushButton* b = dynamic_cast<QPushButton*>(_button); //cast widget to pushbutton int index = layout->indexOf(_button); // find out the index of button in gridlayout int row, col,ax,bx; if(index != -1){ layout->getItemPosition(index,&row,&col,&ax,&bx); // get the koordinate of this item } // Set border color //b->setStyleSheet("border:2px solid #ff0000"); or set Background color b->setStyleSheet("background-color:green"); //make delay time here to Show this Color for only a specific amoun of time like Sleep(MS) in Windows.h // TODO //QThread:usleep() seem not work, QTimer i think also dont work b->setStyleSheet(""); // set stylesheet back } }
Any Solution for this?
Thanks
-
You made it way more complicated than necessary. no need to use QSignalMapper either
connect(button,&QPushButton::clicked,[button]()->void{ button->setStyleSheet(QStringLiteral"background-color:green")); QTimer::singleShot(300,[button]()->void{button->setStyleSheet(QString());}); });
-
Hi and welcome to devnet,
Can you post the code that is triggering the error ?
-
@Yrandom said in Set Delay Timer:
connect(b,&QPushButton::click(),b->void{
Why did you add () after click?
The correct name of the slot is http://doc.qt.io/qt-5/qabstractbutton.html#clicked, so it must be:connect(b,&QPushButton::clicked,[b]()->void{ ...
-
Hi
I make a Programm using C++ and Netbeans with a lot of pushbuttonI would like to do something like this
When i click the button, it should change to the Position i want and Change the border style or maybe Background to red or whatever and after maybe 300ms it should Change back to normal
The part with changing Position worked for me.I used to Google but I didn found any solution. I try something like this but itsnot work
void Game::buttonClicked(QWidget* _button){ // Clicked button identifire with QSignalMapper QPushButton* b = dynamic_cast<QPushButton*>(_button); //cast widget to pushbutton int index = layout->indexOf(_button); // find out the index of button in gridlayout int row, col,ax,bx; if(index != -1){ layout->getItemPosition(index,&row,&col,&ax,&bx); // get the koordinate of this item } // Set border color //b->setStyleSheet("border:2px solid #ff0000"); or set Background color b->setStyleSheet("background-color:green"); //make delay time here to Show this Color for only a specific amoun of time like Sleep(MS) in Windows.h // TODO //QThread:usleep() seem not work, QTimer i think also dont work b->setStyleSheet(""); // set stylesheet back } }
Any Solution for this?
Thanks
@Yrandom You got a lot of good advise from the others. I'll try to add to that.
If you don't wan't do rewrite your code too much, you can change your fuction to something like this.void VerschiebeSpiel::buttonClicked(QWidget* _button){ QPushButton* b = dynamic_cast<QPushButton*>(_button); int index = layout->indexOf(_button); int row, col,ax,bx; if(index != -1){ layout->getItemPosition(index,&row,&col,&ax,&bx); } if(b){//check if valid cast b->setStyleSheet("background-color:green"); //Timer + Lambda-function to reset the button after 1000 msec QTimer::singleShot(1000,this,[=]{b->setStyleSheet("background-color:red");}); } }
-
To both: use qobject_cast when dealing with QObject based classes.
-
@Yrandom You got a lot of good advise from the others. I'll try to add to that.
If you don't wan't do rewrite your code too much, you can change your fuction to something like this.void VerschiebeSpiel::buttonClicked(QWidget* _button){ QPushButton* b = dynamic_cast<QPushButton*>(_button); int index = layout->indexOf(_button); int row, col,ax,bx; if(index != -1){ layout->getItemPosition(index,&row,&col,&ax,&bx); } if(b){//check if valid cast b->setStyleSheet("background-color:green"); //Timer + Lambda-function to reset the button after 1000 msec QTimer::singleShot(1000,this,[=]{b->setStyleSheet("background-color:red");}); } }
thx for this example
it works great.also just mention: i found out other solution for that
using processevents and currenttime
but i want to unterstand how this part workQCoreApplication::processEvents( QEventLoop::AllEvents, 100 );
What is the 100(maxtime) mean ? because i just need to process the Event again (Loop all Event) and the current time will increase automatically.
I dont need to put 100 as Parameter and it still workThx all for the answer
// Delay time for button color void ss::delay(int millisecondsToWait ) { QTime dieTime = QTime::currentTime().addMSecs( millisecondsToWait ); while( QTime::currentTime() < dieTime ) { QCoreApplication::processEvents( QEventLoop::AllEvents, 100 ); } }
-
thx for this example
it works great.also just mention: i found out other solution for that
using processevents and currenttime
but i want to unterstand how this part workQCoreApplication::processEvents( QEventLoop::AllEvents, 100 );
What is the 100(maxtime) mean ? because i just need to process the Event again (Loop all Event) and the current time will increase automatically.
I dont need to put 100 as Parameter and it still workThx all for the answer
// Delay time for button color void ss::delay(int millisecondsToWait ) { QTime dieTime = QTime::currentTime().addMSecs( millisecondsToWait ); while( QTime::currentTime() < dieTime ) { QCoreApplication::processEvents( QEventLoop::AllEvents, 100 ); } }
@Yrandom said in Set Delay Timer:
QCoreApplication::processEvents
Check documentation http://doc.qt.io/qt-5/qcoreapplication.html#processEvents-1
"Processes pending events for the calling thread for maxtime milliseconds or until there are no more events to process, whichever is shorter."
Keep in mind that your solution isn't nice from design point of view and will consume a lot of CPU power. -
@Yrandom said in Set Delay Timer:
VerschiebeSpiel.cpp.cc: In member function 'void erschiebeSpiel::buttonClicked(QWidget*)':
That's not where you should put the connect. my code snippet should go just after you create the button (in the constructor?)
while( QTime::currentTime() < dieTime )
{
QCoreApplication::processEvents( QEventLoop::AllEvents, 100 );
}This is just bad design. you are blocking the main thread and forcing the event loop to kinda keep the UI responsive. Nasty
-
thx for this example
it works great.also just mention: i found out other solution for that
using processevents and currenttime
but i want to unterstand how this part workQCoreApplication::processEvents( QEventLoop::AllEvents, 100 );
What is the 100(maxtime) mean ? because i just need to process the Event again (Loop all Event) and the current time will increase automatically.
I dont need to put 100 as Parameter and it still workThx all for the answer
// Delay time for button color void ss::delay(int millisecondsToWait ) { QTime dieTime = QTime::currentTime().addMSecs( millisecondsToWait ); while( QTime::currentTime() < dieTime ) { QCoreApplication::processEvents( QEventLoop::AllEvents, 100 ); } }
Usually during a while loop, all other tasks are suspendet until the loop or more precisely the function returns. That includes the paint/repaint event that is triggered by
setStyleSheet()
.QCoreApplication::processEvents() is an uncomely way to tell your app, "That with the function, do whatever else is qued".
The Int value you pass to processEvents is a max value in -I believe -ms, you give other Processes to finish their stuff, after that time your code after the call gets processed again.a While loop now is calling that every eventloop-cycle
My advice, don't use it, if you have other options.
-
A wait function like this:
void wait(float sec) { QElapsedTimer timer; timer.start(); while(! timer.hasExpired(sec*1000)) QCoreApplication::processEvents(); }
allows you to simpy do that:
b->setStyleSheet("background-color:green"); wait(0.3); b->setStyleSheet("background-color:red");
Pretty and clean isn't it ?
-
A wait function like this:
void wait(float sec) { QElapsedTimer timer; timer.start(); while(! timer.hasExpired(sec*1000)) QCoreApplication::processEvents(); }
allows you to simpy do that:
b->setStyleSheet("background-color:green"); wait(0.3); b->setStyleSheet("background-color:red");
Pretty and clean isn't it ?
@mpergand said in Set Delay Timer:
while(! timer.hasExpired(sec*1000)) QCoreApplication::processEvents();
Pretty and clean isn't it ?
No, it's not!
Do not use
QCoreApplication::processEvents
if you can avoid it! -
A wait function like this:
void wait(float sec) { QElapsedTimer timer; timer.start(); while(! timer.hasExpired(sec*1000)) QCoreApplication::processEvents(); }
allows you to simpy do that:
b->setStyleSheet("background-color:green"); wait(0.3); b->setStyleSheet("background-color:red");
Pretty and clean isn't it ?
-
@j.hilk Do not use QCoreApplication::processEvents if you can avoid it!
Why ?
Explain any good reason to avoid it.@mpergand said in Set Delay Timer:
@j.hilk Do not use QCoreApplication::processEvents if you can avoid it!
Why ?
Explain any good reason to avoid it.At least used in such a loop->
@VRonin said in Set Delay Timer:No it is not. it uses 75% of one of my CPU cores for absolutely nothing
Its also contrarian to the event-driven programming approach
-
@mpergand said in Set Delay Timer:
Pretty and clean isn't it ?
No it is not. it uses 75% of one of my CPU cores for absolutely nothing
@VRonin said in Set Delay Timer:
No it is not. it uses 75% of one of my CPU cores for absolutely nothing
For .3 sec not a big deal.
I agree, that it's should by used for short period only (< 1 sec)The main drawback I know (i use the same principle on MacOS) is that it can leading to some reentrant call in some cases.
-
@VRonin said in Set Delay Timer:
No it is not. it uses 75% of one of my CPU cores for absolutely nothing
For .3 sec not a big deal.
I agree, that it's should by used for short period only (< 1 sec)The main drawback I know (i use the same principle on MacOS) is that it can leading to some reentrant call in some cases.
-
@mpergand said in Set Delay Timer:
For .3 sec not a big deal.
It is. especially on mobile/embedded hardware. it's just bad design especially when alternatives based of QEventLoop exist (but of course use the async is ALWAYS the best design)
@VRonin said in Set Delay Timer:
It is. especially on mobile/embedded hardware. it's just bad design especially when alternatives based of QEventLoop exist (but of course use the async is ALWAYS the best design)
Ok, add a small QThread::sleep should do the job as well.
Please, can you post an example of a wait function with a QEventLoop instead.
-
add a small QThread::sleep should do the job as well
it does not, reason in link below
can you post an example of a wait function with a QEventLoop instead.
https://forum.qt.io/topic/78715/why-my-timer-is-not-emit-timeout-signal