Set Delay Timer
-
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
-
WOW. All the discussion :)
First off all, thx for the answer.
I have one more question to fullfill my Project. I dont want to start new Topic.I have a class GameKonfiguration
and class MainWindow
and the main()#include "Konfiguration.h" #include "MainWindow.h" int main(int argc, char *argv[]) { // initialize resources, if needed // Q_INIT_RESOURCE(resfile); QApplication app(argc, argv); MainWindow *window = new MainWindow(&app); window->show(); Konfiguration *konfiguration = new Konfiguration(&app,window); konfiguration->show(); return app.exec(); }
in main
Now I make this Programm so far, that when i start, both Windows open and i can Change configuration and the gamefield show and user can Play and actually i can quit the game via configuration. everything fine
Now I want to Combine the menu bar from mainwindow and use the menu bar to open my configuration window.
However the Problem i have is now, i cant include Header a in Header b and Header b in Header a.// mainwindow Header file #include "ui_MainWindow.h" #include <QApplication> //some Header here //try #include "Konfiguration.h" //-- not work because in Konfiguration.h i already include mainwindow.h in oder to use for the Slot etc using namespace std; class MainWindow : public QMainWindow { Q_OBJECT private: Ui::MainWindow widget; QApplication *app; // Try Konfiguration *confi; public: MainWindow(QApplication*); //some function signals: public slots: // function etc ........ void openConfi(); }; // in mainwindow.cpp // Open Game Configuration QObject::connect(widget.SpielKonfiguration,SIGNAL(triggered()),this,SLOT(openConfi())); // End Game QObject::connect(widget.SpielBeenden,SIGNAL(triggered()),app,SLOT(quit())); // Configuration Window void MainWindow::openConfi(){ // in this Slot , the configuration window should open confi->show(); }
Konfiguration.h and cpp
#ifndef KONFIGURATION_H #define KONFIGURATION_H #include <QApplication> #include "MainWindow.h" // some Header here.... class Konfiguration : public QDialog{ Q_OBJECT private: QApplication *app; // here i create mainwindow pointer to Setup the gamefield MainWindow *spielFenster; //some code here public: Konfiguration(QApplication*, MainWindow*); virtual ~Konfiguration(); public slots: void clearText(); // void updateTextN(QString); // void updateTextM(QString); }; //konfiguration.cpp // use the mainwindow pointer to set Slot //Set N, M in VerschiebeSpiel QObject::connect(editN,SIGNAL(textChanged(QString)),spielFenster,SLOT(setN(QString))); QObject::connect(editM,SIGNAL(textChanged(QString)),spielFenster,SLOT(setM(QString)));
So how can I open the Konfiguration Window via the Menu bar of Mainwindow but I can still use the Konfiguration to configure the MainWindow ?
Muss be simple for you guys, but quite hard for newbie :)
thx for your help
-
WOW. All the discussion :)
First off all, thx for the answer.
I have one more question to fullfill my Project. I dont want to start new Topic.I have a class GameKonfiguration
and class MainWindow
and the main()#include "Konfiguration.h" #include "MainWindow.h" int main(int argc, char *argv[]) { // initialize resources, if needed // Q_INIT_RESOURCE(resfile); QApplication app(argc, argv); MainWindow *window = new MainWindow(&app); window->show(); Konfiguration *konfiguration = new Konfiguration(&app,window); konfiguration->show(); return app.exec(); }
in main
Now I make this Programm so far, that when i start, both Windows open and i can Change configuration and the gamefield show and user can Play and actually i can quit the game via configuration. everything fine
Now I want to Combine the menu bar from mainwindow and use the menu bar to open my configuration window.
However the Problem i have is now, i cant include Header a in Header b and Header b in Header a.// mainwindow Header file #include "ui_MainWindow.h" #include <QApplication> //some Header here //try #include "Konfiguration.h" //-- not work because in Konfiguration.h i already include mainwindow.h in oder to use for the Slot etc using namespace std; class MainWindow : public QMainWindow { Q_OBJECT private: Ui::MainWindow widget; QApplication *app; // Try Konfiguration *confi; public: MainWindow(QApplication*); //some function signals: public slots: // function etc ........ void openConfi(); }; // in mainwindow.cpp // Open Game Configuration QObject::connect(widget.SpielKonfiguration,SIGNAL(triggered()),this,SLOT(openConfi())); // End Game QObject::connect(widget.SpielBeenden,SIGNAL(triggered()),app,SLOT(quit())); // Configuration Window void MainWindow::openConfi(){ // in this Slot , the configuration window should open confi->show(); }
Konfiguration.h and cpp
#ifndef KONFIGURATION_H #define KONFIGURATION_H #include <QApplication> #include "MainWindow.h" // some Header here.... class Konfiguration : public QDialog{ Q_OBJECT private: QApplication *app; // here i create mainwindow pointer to Setup the gamefield MainWindow *spielFenster; //some code here public: Konfiguration(QApplication*, MainWindow*); virtual ~Konfiguration(); public slots: void clearText(); // void updateTextN(QString); // void updateTextM(QString); }; //konfiguration.cpp // use the mainwindow pointer to set Slot //Set N, M in VerschiebeSpiel QObject::connect(editN,SIGNAL(textChanged(QString)),spielFenster,SLOT(setN(QString))); QObject::connect(editM,SIGNAL(textChanged(QString)),spielFenster,SLOT(setM(QString)));
So how can I open the Konfiguration Window via the Menu bar of Mainwindow but I can still use the Konfiguration to configure the MainWindow ?
Muss be simple for you guys, but quite hard for newbie :)
thx for your help
the circular includes problem can often be solved with a forward of the class
so instead of ( in the other class header)
#include <myclass>you just
doclass MyClass; // this is a forward
and you are allowed to have
class Other {
MyClass * mc;Since all the use of the Myclass functions, are in the CPP file, it works.
In the CPP file you then include the actual header.
Not sure i explained it good :(
Please see
http://stackoverflow.com/questions/625799/resolve-header-include-circular-dependencies