I have a function that could run in an infinite loop, so I need a way of stopping the function at the press of a button. The problem is that while the function is running, the Qt widgets become unresponsive so I can't just set a stop bool when the button is pressed.
I am unsure of how to do this:
Connect the button signal to a QEventLoop and use that to stop the function (don't know how that would work) or have the function in a separate thread (never done that before)?
Related
I have implemented a GUI and my problem is to handle two tasks at the same time. My code should be provide the opportunity to execute the task by clicking on a Pushbutton or by listening to CAN messages with the read function.
I had the idea to read CAN messages with a while loop until the pushbutton is clicked. Is this a good approach?
Your GUI itself should have some sort of main loop that continuously runs waiting for any updates to process. Each iteration of which, it should be reading the CAN messages and if there is a trigger for a specific task, you should have code implemented that handles that. The same thing goes for any of your push buttons. You should not have any logic that stops checking the CAN if a button is pushed, or vice-versa. Instead, you should keep track of specific events being triggered with a boolean and prevent retriggering them until they are complete/resolved.
I am programming a GUI with wxWidgets. I got a button to open a serial port and receive data. In there is a while(1) loop to constantly receive the data.
Now I want to do a "Disconnect" button to stop receiving.
Is there an event handler or a callback function to interrupt the while and jump out of the loop from the first button, when I press another button?
A wxButton sends a message when it is clicked. Create a handler for this message where you do your "interrruption".
Now, a loop can be only exited from its inner guts. I mean, inside the loop you should check a flag, and depending on the value of this flag continue or exit.
My advice is that you create a worker thread. When the button "connect" is clicked then you create the thread that receives data.
This thread checks an extern flag and finishes depending on the value of the flag.
The "disconnect" button click-handler just sets that extern flag to a value that makes the thread exits when it checks that flag.
Take a look at the thread sample provided with wxWidgets sources.
If you have a while(1) loop in the callback function for "button pressed", you will hang the UI. Callback functions must return quickly.
The quickest solution is to put the while(1) loop into a worker thread. That way your GUI won't hang.
The next problem is how to stop the loop. That's quite easy. Change the loop into:
while (keep_going.load()) {
....
where keep_going is of type std::atomic_bool. Then your "stop" button just calls keep_going.store(false).
Consider this situation:
For a button on a widget: if there is a chance that the button's clicked() slot is delivered (processed) after the widget (that contains the button) gets hided by explicitly calling hide()?
For instance, suppose that there is a timer, and in its timeout() slot, widget.hide() gets called. Coincidentally, The user clicks the button just at the same time time is up.
The question is: Is there a chance that the button's clicked() slot get called after timer's timeout() slot (which hides the widget that contains the button)?
No, the main thread in synchronous respect the GUI actions, so you cannot change the visibility of an object living in the main thread (like your QPushButton) exactly at the same time an user is clicking on it. Also, unless you 're on a multithread app with different events loops, your QTimer will be processed in the main thread too, so it is synchronous respect the UI. In few words: you may get a millisecond concurrence (clicking immediately before hiding it), but not actual parallelism.
If you care about this, maybe you can set a small delay before actually processing the click, just to check if the button was clicked but immediately hidden. In this case you can ignore the user input but it would be confusing. Another option would be to delay hiding the button if it was clicked, so the user doesn't get the wrong visual feedback.
I'm writing a CPP program, and I want to execute a function when the 'X'(shut down) button is pressed.
For example, I have an infinite loop that prints the same thing everytime it iterates, until the 'X' button is pressed, and I want to execute a function before the process ends.
Is there some kind of listener for this matter? Or some other solution maybe (like delaying the process shut down for a few seconds or something)?
Thanks!
If you want to execute something before your process ends, you can register an std::atexit handler. This function will be called before your process exits.
I've been trying to figure out how to make the program stop in a for-loop and wait for a button to be clicked and the for-loop continues.
Isn't there any easy way to stop the loop like QSystem.stop() and in the button clicked function QSystem.star() and the loop continues.
In C++ you could use system("pause") or the program stopped when you used a cin<<. But how do i do this in QT?
Since the userinterface needs its code to run, if you halt event loop (which also means that any function that gets called from within the event loop is blocking, waiting for some event), you also halt the user interface, which means clicks into the window won't be processed. That's why in event based programming, which is what all UI kits do, it is essential to return to the main event handler loop as quickly as possible.
What you can do is create a second thread and wait on a condition variable. The GUI thread can signal that condition variable in the button click event slot.
In C++ you could use system("pause") or the program stopped
Exactly: The program is stopped. Which means it won't fetch events from the operating system. However receiving data from stdin is not an event. It's blocking on streamed I/O. Graphical user interfaces are event based though.
Note that conceptually it's not really impossible to think of a user interface to provide streaming I/O channels. However that doesn't work in single threaded programs. You need parallel execution (coroutines, threads, or such) for a concept like this to work.
You don't need threads, nested event loop will do the job.
int waitUntilSignalIsEmitted(QObject *sender, const char *signal) {
QEventLoop loop;
connect(sender, signal,
&loop, SLOT(quit()));
return loop.exec();
}
// usage:
while(yourLoopCondition) {
// some stuff
...
// pause here
waitUntilSignalIsEmitted(yourContinuationButton, SIGNAL(clicked()));
// loop continuation
...
}