Is there a way to easily determine what slots are connected to a signal or object in PyQt4?
The main use-case for this is connecting all default slots for a given object. For example, maybe I want to enable sorting on a QTableView with setSortingEnabled() but I want to control the horizontalHeader().sortIndicatorChanged signal myself. I need to see what all slots are connected to the sortIndicatorChanged signal and disconnect them.
Ideally I'd like a function like the following:
def print_all_connected(qobject, signal=None):
signals = qobject.signals() if signal is None: else [signal]
for signal in qobject.signals():
for slot in qobject.connectedSlots():
print slot
So a call like print_all_connected(my_table_model, 'dataChanged') would print all the slots connected to the dataChanged signal on the my_table_model slot.
I think standard Qt interprets a call to disconnect() as an automatic disconnection of all slots for the signal it was called on. Unfortunately, I don't think PyQt4 implements this, signals must be disconnected one by one. However, I'd still like to be able to search an object and see what slots or signals it has and print/disconnect them, etc.
In addition, I know there is a QObject.receviers() method that can return the number of 'receivers' connected to a given slot. However, this doesn't tell me who/what those receivers are.
Disconnect works just like in Qt. See the documentation for disconnect in pyQt.
I couldn't find a way to do what you want, but you can check the doku for:
New-style Signal and Slot Support
Old-style Signal and Slot Support
Things to be Aware Of
Related
I have the following Scenes:
Player
Enemy
Attack
When an Attack collides with the Enemy, the Enemy emits a "onHit" signal.
The Player listens for that signal and bounces back.
This is all working good, but now if I duplicate the enemy so there are multiple Enemy scenes, how do I listen to the signal on all of them? Is there a way to grab all instances of a Scene and connect to all of their signals? Is there a better way of sending this message back to the Player?
I'm very new to Godot so any advice is very helpful! Thanks.
Use a Signal Bus.
Yes, you could iterate over the nodes and find all the enemies (e.g. by comparing their script). However, it is easier if all the enemies register themselves to a list (or a group) on _ready. However, you don't need any of that.
The insight is this: An object can emit signals of other objects.
We take advantage of that by creating a Signal Bus. Which is a a common pattern in Godot. It goes as follows:
Create an autoload (singleton) script. Let us call it SignalBus.
In the script, define signals. And nothing else. *In our case, we define on_hit:
signal on_hit
Every place that needs to emit a signal does it from the signal bus. In this case the enemies do this:
SignalBus.emit_signal("on_hit")
And where you need to handle the signal, connect to it. For example on _ready. Something like this:
func _ready() -> void:
SignalBus.connect("on_hit", self, "_on_hit")
func _on_hit() -> void:
# whatever
pass
This way the emitters and receivers of a signal don't need to know each other. They only need to know the Signal Bus. Which is available everywhere (by virtue of being an autoload).
I have started database loading in non-GUI thread with QtCuncurrent::run.
In this nonGui thread I have to create QStandardItemModel* and after that I received model in GUI thread with
model = modelWatcher.result();
on QFutureWatcher finished() signal. It works pretty (UI is builded successfully), but itemChanged() signal is not emitted on item data changes (checkbox state changed). When I creates the model in GUI thread, there are no collisions. Connect works without assert fails:
bool ok = connect(model, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(onFolderStateChanged(QStandardItem*)), static_cast<Qt::ConnectionType>(Qt::UniqueConnection));
Q_ASSERT(ok);
As I can see in that thread (there are no code samples and I misunderstood the main idea) I can't to create model (part of Qt5Gui) in nonGui thread. But it works for me! Ui is builded) Also I have to declare sended type with:
qRegisterMetaType<QStandardItemModel*>("QStandardItemModel*");
And my other sends like:
qRegisterMetaType<QList<QTreeWidgetItem*> >("QList<QTreeWidgetItem*>");
works good (though its also Qt5Gui part).
I dont understand how can I **get the model from nonGui thread with full functionality** like itemChanged signals?
Its something like emit mysignal(QStandardItemModel*); ?
In that case, why other tasks works fine without any emit`s ? including currentChanged signals etc.
When I send model from nonGui thread, some signals have been lost, because model pointer and related data is incorrect if I'm not mistaken. Also QStandardItemModel - is a part of Qt5Gui and its not threadsafe. It means, that model and view should be collected in GUI thread, and data must be sended from worker thread and binded to the model in GUI thread. Its not simple in my situation - I have big tree and I don't want to create my own struct for parsing the tree - but it is a "true way").
I'm using more simple decision - I just sends the parentItem pointer to the new model in GUI thread - and it works.
If anybody knows how to send tree structure from worker thread simple - please tell it in this thread)
In any case - using text-represented data transfer between threads - its more preferred method (like JSON/XML...any yourself representation, based on indexes of items, listed in ``QList>` etc...)
Have you tried this ?
bool ok = connect(model, SIGNAL(itemChanged(QStandardItem*)), this,
SLOT(onFolderStateChanged(QStandardItem*)),
static_cast<Qt::ConnectionType>(Qt::AutoConnection | Qt::UniqueConnection));
I have a basic Qt question on the way it handles Signals and Slots. I am very new to the framework, so pardon me if it sounds stupid. I was wondering if I have certain signals connected to certain slots.
signal1() ---> slot1(){ cout <<"a"; }
signal2() ---> slot2(){ cout <<"b"; }
signal3() ---> slot3(){ cout <<"c"; }
And in my code I call
emit signal1();
emit signal2();
emit signal3();
Does Qt guarantee to print out "abc" to the screen, in other words process the slots sequentially? Or will it spawn a separate thread to execute each slot?
Thanks!
By default:
1) If the signal is emitted in the thread which the receiving object has affinity then the slots connected to this signal are executed immediately, just like a normal function calls. Execution of the code following the emit statement will occur once all slots have returned.
2) Otherwise, the slot is invoked when control returns to the event loop of the receiver's thread. The code following the emit keyword will continue immediately, and the slots will be executed later in the receiver's thread.
More info about connection types here: http://qt-project.org/doc/qt-4.8/threads-qobject.html#signals-and-slots-across-threads
Just to add to Kotlomoy's correct answer :)
You can also control the type of connection from the default by supplying the optional parameter ConnectionType:
connect(obj, signal, obj, slot, connectionType)
Where your main options are:
Qt::QueuedConnection: This will only run when control returns to the event loop of the thread. I.e. will be added to the queue. specify this if you don't want your slot to be processed immediately which can be very useful.
Qt::DirectConnection: Alternatively you can specify direct connection (even between threads if you want), but generally you do not need or want to use this option since it is default when a signal is emitted to a slot within the same thread.
If you use QueuedConnection you grantee "abc" to be printed to the screen in that order.
Its worth noting if a directConnect event occurs while you are processing a previous slot (lets say some other external event triggers a signal like an IpSocket input) then you will get "interrupted". This won't happen in your simple example.
In my application I have the following situation:
an object emits signal removeCharacter
removeCharacter has a part A and B, and after part A is done it fires signal removePath
slot onRemovePath is connected to signal removePath and will remove the path for the character and then fire a signal pathRemoved
slot finishRemovingCharacter is connected to signal pathRemoved and will finish the rest of the character removal process
I don't want to always execute this finishRemovingCharacter logic when I fire the removePath signal
Is there some generic way to achieve the above, preferably something that Qt may already have available?
EDIT: I was hoping there would be a generic way to specify a sequence of signal and slot processing, instead of needing an intermediate slot to send a signal that it is done so the next step can execute.
As I see it, there are only two ways to handle with the situation.
Option 1:
Use two signals for the pathRemoved event. For example finishRemovingCharacter is connected to pathRemoved but NOT to pathRemovedSpecial.
Option 2:
Add proper arguments to the pathRemoved signal and then in the finishRemovingCharacter slot check if it should continue or just ignore this event in which case you'll just return;.
I'm working on a chat application using C and unix low level sockets. I have succeeded in making the console version, but I want to make a GUI for the application.
I would like to use GTK for the GUI.
my problem is how to "synchronize" the socket and the GUI.
because I have to call gtk_main() as the last GTK statement and the application itself is an infinite loop. How can I update the GUI when a message comes in?
You are facing the problem that you have several event systems at once but only one thread. Gtk+ comes with its own event handler, that eventually boils down to a select() which will wake up on any user input or other gtk event. You yourself want to handle networking with your own event handling, which typically consists of a select() on your socket(s) or using the sockets in blocking mode.
One solution is to integrate your events into the event loop of Gtk+.
You can make Gtk+ watch/select() your sockets and call a specific function when their state changes (data readable).
See the section "Creating new source types" on http://developer.gnome.org/glib/2.30/glib-The-Main-Event-Loop.html
Another solution would be to use Gtk+ networking functionality.
Typically you don't want to do something so special with the sockets that it is not easily wrapable with Glib IO Channels. See http://developer.gnome.org/glib/2.30/glib-IO-Channels.html
A third solution is to start a second thread that handles your networking, e.g. with posix threads or Gtk+ threading functionality.
Separating GUI from the worker part of your application is in general a good idea. However for a chat application, it probably does not give any benefit over the other solutions. See http://developer.gnome.org/glib/2.30/glib-Threads.html
This is an example in python with pygobject using GLib.IOChannel to add a watch in the gtk main event loop.
One watch is for listening to new connections.
The other for receiving data.
This is adapted from this pygtk example: http://rox.sourceforge.net/desktop/node/413.html
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib;
from socket import socket
def listener(io, cond, sock):
conn = sock.accept()[0]
GLib.io_add_watch(GLib.IOChannel(conn.fileno()),0,GLib.IOCondition.IN, handler, conn)
return True
def handler(io, cond, sock):
print(sock.recv(1000))
return True
s = socket()
s.bind(('localhost', 50555))
s.listen()
GLib.io_add_watch(GLib.IOChannel(s.fileno()), 0, GLib.IOCondition.IN, listener, s)
Gtk.main()