I'm wanting a paradigm in a Qt4 (PyQt4) program where a component is able to respond to a signal without knowing anything about where it is coming from.
My intial reading suggests that I have to explicitly connect signals to slots. But what I want is for any of a number of components to be able to send a signal, and for it to be processed by another component.
Comparing with another toolkits, for example, in wxWidgets I would use events. These automatically propogate up from child windows/objects to parents. At each level they can be handled. This means if I have a lot of children which may emit the same event, I don't have to explicitly connect all of them to the handler. I can just put the handler in the parent, or some higher level in the window hierarchy. This means that only the event generator and consumer need to know about the event at all. The consumer doesn't need to know where the source of the event is, how many such sources there are, or anything else about it.
Is this possible in Qt - is there another approach? Maybe there is an alternative event mechanism to signals and slots?
This isn't easily possible - you have to have something that knows about the signaling object and the receiving object to connect the two. Depending on what you need, however, you might be able to set up a class that mediates between the two (so objects with signals tell the class they exist, and have such-and-such a signal, while objects with slots tell the class they exist and have such-and-such a slot to connect to a given signal, and the mediator class tracks both of those, making connections when necessary).
Don't you just want a good old fashioned method invocation? The response is just the return value of the method.
Signal handlers do NOT know the emitter (only the signal type) and emitters do NOT know what handlers are connected. Many handlers can connect to the same signal and they are executed in the order of connection. A signal can be emitted from many places.
Related
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.
When I simply use 'connect', there is no way I can specify the order in the callbacks will be called. Having connect_before and connect_after to connect before/after the default doesn't serve my purpose. I want something like connect_first and connect_last or anything else that will help me specify the order in which callbacks connect to a signal.
Something like this?
something.connect_first('my-signal', callback1)
somethingelse.connect_last('my-signal', callback2)
There is only one explicit ordering guarantee for GObject signals:
the class closure added when creating a new signal with G_SIGNAL_RUN_FIRST will be called before all callbacks added using g_signal_connect()
the class closure added when creating a new signal eith G_SIGNAL_RUN_LAST will be called after all callbacks added using g_signal_connect() and before all callbacks added using g_signal_connect_after()
This means that you can only control whether a callback is invoked before or after all other callbacks connected manually when you're creating a new signal - for obvious reasons, since you may want to provide an initial state at the start of an emission chain, or you want to ensure a stable state at the end of an emission chain.
As for the order of the callbacks added using g_signal_connect(), there is no explicit guarantee of any ordering. There's an implicit order, the order of connection, though, that won't likely ever be changed. Remember that signal handlers can install new handlers, or disconnect them, or block the signal emission, so relying on a specific order is usually an indication of a design problem in the code.
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.
I'm learning PyQt (I haven't used C++ Qt before).
I don't understand the reason for signals and slots. That is, it seems I can do everything by calling the methods of classes directly. Doing so seems more Pythonic, uses less code and is easier to read. What am I missing?
For clarification, I'm asking why I would do this:
def mouseReleaseEvent(self):
self.clicksignal.connect(ui.iconClicked)
self.clicksignal.emit()
when I can do this:
def mouseReleaseEvent(self):
ui.iconClicked()
The reason signals and slots exist is because you cannot change the GUI from any other thread of the application except the UI thread.
If you have some heavy CPU intensive calculation to do, or any task that waits for IO or something like that... if you do it the UI thread (for example if you fetch a url or something that lasts some time), your UI thread will be busy, and the GUI event loop wont be able to update itself, so the GUI will seem frozen.
To do these kind of operations. you execute them in a separate (background worker) thread, so the UI thread can continue updating the GUI.
Now the problem is that you cannot access the elements of the GUI and change their state from any other thread except the UI thread. So signals and slots are introduced. When you emit a signal it is guaranteed to be caught in the UI thread, and the slot will be executed in the UI thread.
I'm not exactly sure what you try to accomplish in your example, but this is the main reason why signals and slots exist. Basically UI thread should only deal with the UI, and everything else should be done in the background worker thread that sends a signal that gets caught in the UI thread and the slot that update the GUI is executed in the UI thread.
Well... yes, you can. But you need to think bigger. In your example code, caller of mouseReleaseEvent must have the reference to the object that receives the notification, and explicitly invoke appropriate method. Using slot & signals mechanism decouples event producer (e.g. widget) from event consumer - pretty much arbitrary other object. This makes setting up communication and control flow easier and external to the low-level UI components, which is the good thing. It also makes such components reusable - by moving wiring code outside, we make it independent of the application logic.
In addition to the answers by #ViktorKerkez and #Wilbur, signals and slots provide a notification system of fire and forget, as well as decoupling classes.
A great advantage of this is that a class can emit a signal, not knowing what or who is going to receive the message. It may be just one object that has a slot connected, or it could be dozens. Alternatively, you may want a single class with one slot that is connected to multiple signals. So it can be used as a notification system.
For example, imagine a program where many different types of objects send information to a log. The objects simply emit a Log(text) signal and do not care about what actually does the logging. These signals can be connected to a log class which can be either logging to a file, over a network, to the screen, or all at once. The objects logging don't care.
I have trouble doing cleanup just before the application quits - my cleanup is called before other essential events are happen.
Currently I am using
QObject.connect(self.qtApp,
SIGNAL("lastWindowClosed()"),
self._lastWindowClosed)
My application consists of a single QtGui.QDialog, that throws SIGNAL("accepted()") or SIGNAL("rejected()") (OK or Cancel buttons). If I do my cleanup as shown above, I miss those events. If I do my cleanup on SIGNAL("aboutToQuit()"), I do not miss those events.
I fail to discover meaningful documentation on any of the two signals. For example PySide's documentation on aboutToQuit and lastWindowClosed talks about some filepths and nothing related to the lifetime of the application.
It appears that I need to use aboutToQuit(). Where can I find meaningful documentation on this signal, so that I am sure no events are missed before it?
See the QCoreApplication::aboutToQuit documentation page:
The signal is particularly useful if your application has to do some last-second cleanup. Note that no user interaction is possible in this state.
So if you want to do cleanup, this signal should be used.
The lastWindowClosed signal is emitted when all windows are closed. It doesn't necessarily lead to the application termination. And emitting this signal on application termination is not guaranteed (for example, it will not be emitted when closing application programmatically using QApplication::quit).