How do i call GUI elements in different Qt threads? [duplicate] - python

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.

Related

Compatibility Between PyPubSub and PyQt

I have been trying to find the most elegant way to decouple my programs from the GUI, such that I can change my front-end without needing to re-write a whole lot of code.
I work with threads a lot, so I often have the need to notify the main GUI thread of asynchronous happenings either through events (for wxPython) or signals (for PyQt). I have experimented a bit with PyPubSub, which may be what I am looking for, but while there are tons of wxPython examples (since it was originally included with it in early development).
I am not aware if there is a 'proper' way to use it with PyQt without running into race conditions. If anyone has some insight on this, I would really appreciate it!
PyPubSub's sendMessage() will call listeners in the same thread as the sender (default Python behavior). In a multithreaded GUI app, you must ensure that listeners that interact with GUI are called in the main thread. Also threads execute independently, so you need each thread to call its own listeners, based on a timed or idle callback mechanism.
The way to call listeners in the correct thread in PyQt is via signals. PyPubSub can still be used in a multithreaded PyQt GUI, but the mechanism used to transfer the "message" from sender to listener would have to be via a signal. There isn't one best way to do it I don't think, depends on details of your app design. You could for example have a QtPubsubHandler that derives from QObject and gets created in main thread, and a QtPubsubSender class that also derives from QObject and gets created in each worker thread. The QtPubSubSender defines a custom signal, say pubsub, which QtPubsubHandler connects to. Then to send a message, the sender does qtPubsubHandler.sendMessage(topic, **data), which causes a pubsub signal to get emitted, which Qt properly queues and eventually signals the QtPubsubHandler, which actually calls pub.sendMessage().
There are many other ways, but you get the general idea: two classes that derive from QObject, and one of them does the actual sending in the same thread as the intended listener, the other uses a signal so everything is thread safe. Actually you don't have to use PyQt signals: but then you would have to have a queue in main thread and have an idle callback that allows it to process any items on the queue.

Python: Execute callback method in main thread

Not wanting my GUI to freeze, I've decided to use a thread for a file operation. Currently I'm using thread.start_new_thread(self.openFile, (filepath, self.openedFile)) to do so, with self.openedFile being my callback method. Inside self.openFile it is just invoked using callback(success).
But unfortunately I couldn't figure out how to execute my callback in the main thread instead of the newly created one. This is required as the GUI cannot be modified from another thread.
I really appreciate all your help!
The thread owning the GUI will have to periodically check a Queue.Queue instance on which other threads can put work requests (e.g a callback function and arguments for it).
How easy or hard it is to insert such checks within a GUI's main loop is 100% dependent on exactly what GUI framework you're using.
For example if you're using Tkinter, the after method of widgets lets you do such periodic checks, as explained e.g at Run an infinite loop in the backgroung in Tkinter .

PyQt : Emtting signal from QThread to QWidget

I've been meaning to implement a chat client/server, with PyQt handling the GUI front. The problem I'm facing is when I want to tell an already connected client that another new client has joined. Initially I worked it around by adding a "refresh users" button which sends the client the updated list. However, now when a client has to message another, I realise that I will obviously have to create a separate thread which keeps on checking for data from the server. I have trying since yesterday, reading various posts/answers, forums but still can't get this to work.
What I want is a separate thread which is executed at the start of the program that checks for data from the server and can emit signals that instigate the function in a GUI thread to change the users list. How do I make a thread that works constantly and emits signals that can be caught by the main GUI loop ? And how should I catch the signal ?
Same as with other Qt components: you create a QThread for your network management, the QThread derived class emits signals with some data coming from network; on the main thread side, you have QObjects and QWidgets that you connect to those signals. Take a look at the following (in that order):
Qt Threading Basics
Thread Support in Qt
How to use QThreads
Another How to use QThreads
what is the correct way to implement a QThread... (example please...)
Once you have read these and tried your own code, then you can post a new question with more specific issues you are having. Otherwise, your question is too broad.

Checking threadsafe-ness in python?

This is my first foray into threading, so apologies for any obvious mistakes.
I have a PyQt widget, from which a new process, prog, is run in a different thread. In my main thread, I'm also redirecting stdout to a read-only QTextEdit. However, I get errors referring to recursion, and I'm worried that my threads are interfering in each other in a way which causes a print statement to go into an infinite loop. I only get these errors if I run prog from the GUI, and not from the command line. My stdout redirect is using the code in this SO answer
In pseudo-code, this is basically what I've got:
gui.py
class widget(QWidget):
def __init__(self):
self.button = QPushButton("GO!", self)
self.button.clicked.connect(self.start)
def start(self):
self.thread = TaskThread()
sys.stdout = EmittingStream(textWritten = self.outputText)
self.thread.start()
def outputText(self):
#as in answer provided in link (EmittingStream in separate module)
prog.py
class TaskThread(QThread):
def run(self):
'''
Long complicated program; putting in simpler code here (e.g. loop printing to 10000) doesn't reproduce errors
'''
Is there any way of finding out if my recursion is caused by an infinite loop, or by anything else?
Is my code obviously thread-unsafe?
How do you make functions guaranteed to be threadsafe? (Links to tutorials / books will be good!)
This is tricky, but I think that your code is thread-unsafe. Specifically, looking at other stackoverflow answers (here and here) it appears that you should not be accessing a Qt GUI object from another thread than the one it was created in (even a QThread).
Since any call to print in your code now accesses a Qt GUI object, it seems this is very thread unsafe.
My suggestion to make it safe would be to:
Have a QThread, inside of which you have instantiated the output box (it is thread safe to access a Qt GUI object from the thread it was created in, and it does not have to be created in the main thread) Qt GUI objects are not reentrant and must be created and used in the main thread only, see here As such you will need a QThread to post events back to the main thread (using the Qt signals/slots mechanism which can be thread safe when done correctly)
Have this QThread blocking on reading from a Python Queue. When it gets something from the queue, it places it in the Qt text box posts it back to the main thread, and the main thread will update the output box.
Modify your EmmittingStream to place things in the Queue, rather than directly into the Qt output box.
I can see you have located where the error is. But without the code there is not much that I can tell.
Filling your needs of direction, I'll point to you to Python profiles. Since it looks like you need some python profiling tools.
http://docs.python.org/2/library/profile.html
and a answer about the subject
How can you profile a Python script?
In a Qt application you must use one single thread to handle the all the gui part. You can use other threads for computations, but not for user interface.
Just post messages about updates in a queue in the worker threads and use the main thread to pick up those messages and update the GUI.

Assigning priorities to wxPython events

Is there anyway to assign priorities to specific wxPython event?
I periodically call a method using a timer after starting my GUI. But I want to be able to get out of this method as soon as the user presses a button. Is this possible without having a worker thread?
Not that I'm aware of. The events are added to the event queue in the order they are received. You might be able to do this with a thread where the process is running in the thread and you kill it. You might try asking on the wxPython mailing list for other ideas though. A couple of the core developers are there and they might have some insights for you.

Categories