Qt Connect Parent Slot
This article is nominated for deletion. Reason: Outdated information. PySide is obsolete. Please raise your support/opposition to this nomination in the article's discussion page. |
Qt Connect Parent Slot Machine
Qt Connect Signal Parent Slot
Qt connects widgets by means of a nice designed scheme based on the idea that objectS may send signalS of different typeS to a single object instance: This is a screenshot of the example code running. QtCore.SIGNAL and QtCore.SLOT macros allow Python to interface with Qt signal and slot delivery mechanisms. This is the old way of using signals and slots. The example below uses the well known clicked signal from a QPushButton. The connect method has a non python-friendly syntax. Build complex application behaviours using signals and slots, and override widget event handling with custom events. As already described, every interaction the user has with a Qt application causes an Event. There are multiple types of event, each representing a difference type of interaction — e.g. Mouse or keyboard events. Qt's signals and slots mechanism ensures that if you connect a signal to a slot, the slot will be called with the signal's parameters at the right time. Signals and slots can take any number of arguments of any type. They are completely type safe.
This page describes a few alternative approaches for connecting signals between QML and PySide. Simple illustrative examples about the signal connectivity are also provided in the pyside-examples repository. Browse the git tree directly or download a tarball of all examples and refer to the examples/declarative/signals directory.
- 1Connecting signals from QML to Python
Connecting signals from QML to Python
Connecting a signal from QML to Python is the most common use case. This allows for example connecting button clicks and other user interface events in QML to the backend logic written in Python.
There are multiple alternative methods for connecting QML signals to Python. The methods are not mutually exclusive; any of them can be used in a single program (and even for a single signal, if need be).
Explicitly calling a Python slot from QML
If the Python object is exposed to QML using setContextProperty
, you can call any slot of the object explicitly from QML, as shown in qmltopy1. First, you define a class in Python, inheriting from QObject:
class Console(QtCore.QObject):
Then, the Python object is instantiated and connected to the QML context:
con = Console()view = QtDeclarative.QDeclarativeView()context = view.rootContext()context.setContextProperty('con', con)
After this, the object is accessible in QML and any slot can be called just like a function:
MouseArea {
}
Returning a value from a slot
It is possible for slots to return values to the QML caller (see example qmltopy2). In this case, the Python slot needs to define an explicit return type:
Then the Python object is exposed to QML, after which it can be called just like a function:
Connecting signals from QML to Python using a top-level QML signal
If you prefer to handle the signal connection in Python, the simplest way to do it is to declare a top-level signal in QML and connect that to a Python slot as shown in example qmltopy3.
First, in the top-level QML item, declare the signal:
Rectangle {
signal textRotationChanged(double rot)
[…]
Then, in some other QML item, make some other signal handler emit this signal:
Finally, in Python, acquire the QML root object and connect the signal:
This approach has the benefit of hiding the Python class behaviour from QML. On the other hand, this approach requires the Python code to have some knowledge of the QML item contents.
Connecting a signal from a specific QML item to Python.
It is also possible to acquire a specific QML item and connect a signal directly to it as illustrated in example qmltopy4.
In principle, this approach doesn't require any extra consideration in QML. Unfortunately, in practice it may be difficult to find the proper QML items without assigning them object names:
Then, in Python, it is simple to find the desired item using findChild
and connect a signal to it:
Although initially tempting, this approach ties the QML and Python codebases pretty tightly to each other. Also, having to define the object names in QML makes the approach less than optimal.
Connecting signals from Python to QML
It is also possible to connect signals from Python to QML when e.g. changes in the model data need to be reflected in the UI. Example pytoqml1 illustrates how to do that.
First, a function is defined in QML:
QML functions appear as slots in Python, so it's a simple matter to connect a signal to them:
This allows for fairly clean and straightforward delivery of signals from Python to QML.
Back in the old days, signals and slots connections were set up for compile time (or even run time) manually, where developers used the following sentence:
this is, we stated the sender object's name, the signal we want to connect, the receiver object's name and the slot to connect the signal to.
Now there's an automatic way to connect signals and slots by means of QMetaObject's ability to make connections between signals and suitably-named slots. And that's the key: if we use an appropriate naming convention, signals and slots will be properly connected without the need to write additional code for that to happen. So by declaring and implementing a slot with a name that follows the following convention:
uic (the User Interface Compiler of Qt) will automatically generate code in the dialog's setupUi() function to connect button's signal with dialog's slot.
So back to our example, the class implementing the slot must define it like this:
We then write the method's implementatio to carry on an action when the signal is emitted:
In brief, we have seen that by using automatic connection of signals and slots we can count on both a standard naming convention and at the same time an explicit interface for designers to embrace. If the proper source code implements such a given interface, interface designers can later check that everything is working fine without the need to code.