PyQt5 - How to make a loop wait for QMessageBox response in a different thread - pyqt5

I'm using PyQt5 to develop an app. I have a situation where I need to run a for loop and if a certain condition is met, I show a QMessageBox to let the user choose if he wants the loop to continue or to stop.
The QMessageBox is displayed using a different thread that the thread for the loop, otherwise the UI freezes. So basically what is happening is that once the QMessageBox is called the loop will go on without waiting for the value from the QMessageBox.
From the UI I start a new thread and start running the loop. From within the loop I send a signal to display the QMessageBox. The common way to handle this is start the QMessageBox in a thread and once a user reacts, send another signal with the user input. This works just fine, but when it comes to use this inside the loop I cannot just cut the loop and use the callback signal to then run it again from where I left it. I need to actually stop/block the thread where the loop is running until the user reacts.

Related

Stop button in LabVIEW cannot be pressed during while loop execution inside an event structure

I am currently working on a LabVIEW project and have found myself stuck on how to make a while loop exit when I press the abort (stop) button. For a simple while loop I understand how to do this - but the problem is that this while loop is nested inside of an event structure and I'm guessing that the button cannot be pressed while the loop is executing. Attached here is a picture of part of my code (that contains this specific event case which is causing me problems): To spend a little more time explaining what the problem is - I think the code is doing what I want it to do (namely output a set of commands in a repeated cycle with a wait timer) but I cannot stop the code mid cycle (pressing the abort button with my mouse does nothing - as in the button doesn't show it being pressed and the indicator shows no change, I also can't use any other functionality of my program during the cycle which I'm assuming is related). And I do not want to stop the LabVIEW program from running entirely - just the code inside the while loop pictured above. This is what the front panel is configured too for completeness:
Essentially what I want to happen is the while loop to execute when I press DWG and in the middle of the cycle be able to abort it. Sorry if my code seems a little messy. Additionally, I've tried the same code with a for loop originally (via a conditional terminal so it could stop early) and that didn't work either. Thanks for any help I appreciate it!
Your problem is that inside the event structure, by default the UI is frozen so no UI actions (keyboard/mouse/etc) are processed until you exit that frame.
Option 1. You can right click the Event Structure and select "Edit events handled by this case" dialog and then uncheck the "Lock panel" checkbox -- that will allow the UI to be live while you are in that frame. I do not recommend this solution generally unless you have an extremely simple user interface because it leads to the user being able to change controls without the events behind those controls being processed (not a good UI experience for users). But if the UI is simple enough, that works.
Option 2. You can create a user event that is the code you want inside your While Loop. When the Deg Wait Go button is pressed, use the "Generate User Event" node to trigger that event. Do the same thing in the user event case so that the event re-triggers itself if and only if the Abort button has not been pressed.
Option 3. Create a separate loop OUTSIDE your UI loop that does your processing with some sort of command queue running between the UI loop and that other loop. The other loop moves into various states at the request of the UI loop... it's the one that does nothing until it receives a "go" message and then keeps looping until it receives a "stop" message. You can Google "queued message handler" for extensive details of this solution. This is the most common solution for complex UI requirements, especially useful for separating concerns of the UI code from the execution code.

Show a progress bar while a function runs in a loop until it returns a value

I have a function that runs an sql query for data that may or may not be there. Since I need to run this function continually until it returns the proper value how can I run a progress bar until the loop finishes.
status = Logic.ProcessResource(currentInstance)
While status.woID.Count <= 0
status = Logic.ProcessResource(currentInstance)
End While
How can I run this and show another form with a progress bar until the loop exits?
My comments as an answer...
Put that code into a different thread, then use a ProgressBar in "Marquee" mode to indicate an operation that is ongoing, but has no known ending time.
Yes...but you still need to put the query/loop in a different thread...otherwise the main UI thread will to be to busy to animate and remain responsive to the user.
Look at the BackgroundWorker control, or using a Task, with Async/Await.
You'd show the form, start the worker, wait for worker to finish, then close the form. The BackgroundWorker() has UI friendly events like RunWorkerCompleted that are already marshaled to the UI thread for you.

How to update a NSTextField Value during an action?

I am running a lengthly task in an Action and I would like to have a display of where I am at. For that I created a Text Field and I tried it with setStringValue:
[textField setStingValue: [NSSting stringWithFormat:#"%ld",currentValue]]
The code works but unfortunately it is not updating the NSTextField after every iteration but rather when the whole Action is done.
What am I doing wrong?
This is because applications with the Cocoa framework use an event loop to perform operations, and events occur in a completely serial fashion.
An event is basically any kind of action that the framework designer could not predict or found convenient to have run in a delayed manner. Since you can't predict when clicks will be performed, they need to be considered events; and for efficiency reasons (since you don't want to repaint a component multiple times if you don't need to), the repaint actions are events too.
Your action runs in response to a user event (for instance, a click on a button is an event) and therefore blocks all other events waiting in the queue until it's complete. However, components are repainted in response to a different, framework-triggered event, and as such the text field must wait until your action completes to repaint itself. This is why you cannot visually change the value of a text field from inside an action.
In order to notify your user of the progress of your task, you'll need to run it on a different thread. There's a lot to say about threads, so you should probably read some about them. I'm also sure that there are plenty of examples of how to run a long action in a background thread and update the UI accordingly for Cocoa all over the Internet.
When you click on a UI component, and it enters the Action block, the code is running on the main thread, the same thread that is painting the UI. If you run a long running operation in that block, it isn't going to paint until you are done because it is busy doing whatever you have it doing - you have hijacked the paint thread.
As said elsewhere, you need to spawn another thread, and then have the new thread perform the long running operation, and occasionally send messages to have the UI be updated by the main thread.
As a next step, go read the Apple documentation on NSThread, specifically:
+ (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument
Be aware that threading is a non-trivial domain area, and be ready for some wierd behavior if you aren't careful.

VB 2010 - Stop a loop with a button

I am using VB 2010 , I have a loop that takes something like 5 minutes until it's finish.
I want to allow the user the option to stop it in the middle or whenever they want.
There's a button which starts the loop , and after I click it the loop starts running and the button is sort of "stuck".
I saw something called "background work" in the VB Toolbox, can it be a solution to my problem?
Start your loop in separate thread and set a flag which directs the action of the loop . Keep polling for this flag to see whether user wants to stop the thread inside the loop on thread . See BackgroundWorker
I think background worker would work, but a very simple solution if to create a boolean variable (visible in scope to your stop button and the logic loop) that controls stopping inside your loop. Your stop button would set the variable to true and the next time that code is hit, it would stop. you may need an application.doevents inside your loop at the end to allow the button's event to fire. This is not an ideal way, but is certainly simple.

What is event loop in ios life cycle and what is its usage and what it does?

I need to know what the event loop in the ios life cycle does?.
Can any one suggest me regarding this??
The best answer is probably the one provided by Apple in the "Main event loop" section of the Cocoa Application Competencies for iOS document.
In the main event loop, an application continuously routes incoming events to objects for handling and, as a result of that handling, updates its appearance and state. An event loop is simply a run loop: an event-processing loop for scheduling work and coordinating the receipt of events from various input sources attached to the run loop. Every thread has access to a run loop. In all but the main thread, the run loop must be configured and run manually by your code. In Cocoa applications, the run loop for the main thread—the main event loop—is run automatically by the application object. What distinguishes the main event loop is that its primary input source receives events from the operating system that are generated by user actions—for example, tapping a view or entering text using a keyboard.
Incidentally, if you're relatively new to iOS development, I'd really recommend a read of this document, as it'll answer a lot of questions you probably have.