Update QThread from GUI Widgets - python

I've seen this question asked in reverse a bunch of times - how to update the GUI from a subclassed QThread - but I actually want to do it in reverse. I have an application which displays the feed from a camera continuously and indefinitely, and the camera runs in a separate thread. I have the camera feed displayed in the GUI using signals from the QThread. The camera controls are in the main GUI window, and I want to be able to send those updates to an already-running camera thread. What would be the best way to do that? Thanks.

If you're using the default QThread::run() implementation which runs an event loop, then you can create a slot on the class and invoke it as a QueuedConnection (which should occur automatically).
Otherwise, you'll need to use standard thread synchronisation primitives, such as QMutex to safely access the same data from both threads.

Related

Python multithread and (shared variables || Qt)

i'm redesigning my software because the last one i did crashed due to a wrong access to a Qt interface by a process started with
serialThread = threading.Thread(target=serialCycle)
serialThread.setDaemon(True)
serialThread.start()
serialThread mainly wait for incoming serial data, decode them and place them in a list (probably i'll move to a numpy array). Informations about connection (serial port, speed, how many data have been received) have to be written in the qt ui. I mainly use global variables to exchange informations between main thread and the serial one; i can ensure that each variable is written only by one thread and read from the other to avoid problems.
The Qt updating is a bit hard to do sending informations to main thread so i looked for another solution. I found this thread ( Updating GUI elements in MultiThreaded PyQT ), but i didn't get the point. If i start a thread with slot and signal can't I have crashes due to multiple access to the same variable?
(Question1) started thread runs in parallel and so they shouldn't change the qt interface...
(Question2) Can't an entire .ui window be loaded "linked" to a different thread so this thread can update it (and obviously not the main thread)
(Question3) Which one is the simpliest way to have a gui that can be updated by different thread about the self status (and to let the user to change parameters)?
Thanks

wxpython 3.0 & multiprocessing - update GUI from background process

From my wxpython GUI app I have an rsync task that I kick off as a multiprocessing.Process.
The idea is to update a wx.textCtrl with the constant output from this background process.
I am using a pubsub subscribe method.
The functions work fine but I can't get the textCtrl to update.
If I use a CallAfter method I get this crash/error:
The process has forked and you cannot use this CoreFoundation
functionality safely. You MUST exec(). Break on
THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC()
to debug.
If I don't use that method and I try to append the text directly to the textctrl nothing happens.
Any ideas?
Thanks!
Adam
The problem is that the child process can't write back to the main process. Use a queue to pass messages back to the main process, and update the control from within a timer or a background thread that waits for messages from the queue.

QT/PySide processEvents call locks up

Why would a call to processEvents block doing nothing for up to 9 seconds?
I have an application with a PySide-based QT interface, where the UI code sits as a decoupled layer over the lower level actual application logic. When the user performs an action which executes lower level application logic that may run for a while, effectively what happens is:
Directly on the GUI thread a progress dialog is displayed.
Directly on the GUI thread, the lower level logic starts a worker thread.
Directly on the GUI thread, the lower level logic loops updating the progress dialog (indirectly/decoupled) and ticking the application event queue via QtGui.qApp.processEvents() (again indirectly/decoupled).
On the worker thread, QT functions are invoked (again indirectly/decoupled) in reaction to events, and these happen on the GUI thread via slots/signals, running when the GUI thread (as mentioned above) calls processEvents().
Directly on the GUI thread, before the loop exits, the last processEvents() call blocks for around 9 seconds. This is after all the logic on the worker thread is over and done with, and there are no more functions waiting to run on it via signal/slot calls. Nothing related to my application is happening in this call. What is it doing there? Why is it blocking? I've tried passing in a max processing time of 300 ms and seeing if it exits, but this makes no difference. The call locks up as long as it wants to.
The progress dialog closes and the user gets focus back.
This is all spread over a lot of files, implemented in a decoupled manner. I'll try and provide snippets to give a picture of the flow.
The decoupled lower level logic worker loop:
while not completed_event.wait(0.1) and not work_state.is_cancelled():
work_completeness, work_description = work_state.get_completeness(), work_state.get_description()
for client in self.clients:
if work_completeness != last_completeness or work_description != last_description:
client.event_prolonged_action_update(client is acting_client, work_description, step_count * work_completeness)
# THE LAST CALL TO THE NEXT LINE LOCKS UP FOR NO REASON
client.event_tick(client is acting_client)
last_completeness, last_description = work_completeness, work_description
The PySide/QT layer client event_tick function:
def event_tick(self, active_client):
# THIS IS WHERE THE LOCK UP HAPPENS
QtGui.qApp.processEvents()
Signal/slot usage in the PySide/QT layer to get worker thread calls happening on the GUI thread:
def event_pre_line_change(self, active_client, line0, line_count):
self.pre_line_change_signal.emit((line0, line_count))
def event_post_line_change(self, active_client, line0, line_count):
self.post_line_change_signal.emit((line0, line_count))
def event_uncertain_reference_modification(self, active_client, data_type_from, data_type_to, address, length):
self.uncertain_reference_modification_signal.emit((data_type_from, data_type_to, address, length))
The reason that I delegate the calls on the worker thread over to the GUI thread using signals/slots, is that this is what PySide/QT requires given they will update the UI.
Reproduction case if you want to dig deeper:
Download and get the code running according to the GitHub project readme text.
Download the test file "NEURO" (<200KB in size) from mega (apologies, it was easiest site to upload to).
Load NEURO in PeaSauce.
Go to offset 0x1A19E (CTRL-G)
Change the data type to code (Menu: Edit / Change address datatype / Code)
Observe progress dialog come and go.
Observe ~9 second lock up.

How to call GUI elements in different Qt threads?

I have an application in which a thread (not main thread) needs access to the GUI's elements (send a click action, show a message box, etc). I am working in python and Qt and also know that it is not possible when in not main thread.
Is there a way to do it? I mean to send the action that I want to do in the thread to the main thread.
Here is a good tutorial on how to use Qthread: http://joplaete.wordpress.com/2010/07/21/threading-with-pyqt4/ . This will show how to call the GUI elements in different and custom threads. Hope this helps.

Terminating a wxPython app cleanly

I'm working on a wxPython app which has multiple frames and a serial connection. I need to be able to exit the app cleanly, closing the serial connection as the app terminates.
What is the best way to do this? Should this be handled by a subclass of wxApp?
Thanks,
Josh
Not totally sure what you're having trouble with here, but I'll take a shot in the dark and assume this is a program organization/design question.
There may be better ways that I'm unfamiliar with, but this is what I'd try to do: create a "parent" object (doesn't have to have any particular type) that keeps references to the multiple frames. When one of the frames receives the exit event from a menu or what have you, it calls self.parent.broadcast_quit(), which sends a quit event to each of the frames it holds references to.
This way of doing it kind of expresses a view-controller separation, where the frames are part of the view and the parent object is a tell-me-when-to-shut-down controller -- the parent can nicely encapsulate the connection teardown as well, since it can stay informed on which frames have shut down and when. You can keep details on how to tear down the view in the frames themselves, and then can send an "I'm finished" message back to the controller during their teardown, triggering some final teardown on the parent side.
See the docs for wx.PostEvent and Custom Event Classes. (Events are a nice normalized way of expressing cross-window messages in a non-blocking GUI.)
I usually use my close button's event handler to close connections and what-not before closing the frame. If you want to catch the upper right "x" button, then you'll need to bind to EVT_CLOSE. Unfortunately, when you do that, you need to call your frame's Destroy() method rather than its Close() method or you'll end up in an infinite loop.

Categories

Resources