I would like to connect the activated
signal from a QML ListView
to a pyqtSlot
decorated method from my Python3/PyQt5 (5.6) code.
My current approach is to load the QML scene in my code through QQmlApplicationEngine
and then use findChild()
to get a reference to my ListView
.
The problem is, that I can only find the ListView when searching for a QObject like findChild(QObject, 'myList')
. But htis object does not give me access to the activated
signal, most likely because this signal is only defined for QAbstractItemView
and it descendants.
So if I try findChild(QListView, 'myList')
the result is None
. Therefor I'm not able to get to the activated
signal. Is this a bug in PyQt5 or is there another way for me to connect to this signal?
Here is some minimal working example.
list.py:
import sys
from OpenGL import GL
from PyQt5.QtCore import QUrl, QObject
from PyQt5.QtWidgets import QApplication, QListView
from PyQt5.QtQml import QQmlApplicationEngine
# Main Function
if __name__ == '__main__':
# Create main app
app = QApplication(sys.argv)
# Create QML engine
engine = QQmlApplicationEngine(app)
# Load the QML scene from file
engine.load(QUrl('List.qml'))
for root in engine.rootObjects():
node = root.findChild(QListView, 'myList')
if node:
# At this point I would like to connect something to the
# node.activated signal
print(node)
# Execute the application and exit
sys.exit(app.exec_())
List.qml:
import QtQuick 2.0
import QtQuick.Window 2.2
Window {
visibility: Window.FullScreen
visible: true
ListView {
objectName: "myList"
anchors.fill: parent
delegate: Item {
width: parent.width * 0.8
height: 40
Row {
id: row1
Rectangle {
width: 40
height: 40
color: colorCode
}
Text {
text: name
font.bold: true
anchors.verticalCenter: parent.verticalCenter
}
spacing: 10
}
}
model: ListModel {
ListElement {
name: "Grey"
colorCode: "grey"
}
ListElement {
name: "Red"
colorCode: "red"
}
ListElement {
name: "Blue"
colorCode: "blue"
}
ListElement {
name: "Green"
colorCode: "green"
}
}
}
}
You can do that by using QQuickView
instead of QQmlApplicationEngine
.
I changed your python script to add a new class which inherits from QQuickView
, and added a signal to the QML object named "myList".
Moreover, into the QML I removed the Window
type for Item
type (you can't use Window
with QQuickView
). If you want to display your application in full screen, you'll have to specify it into MyView
class.
In the example, if you click on one of the colored rectangles, the index will be displayed in the console.
list.py:
import sys
from PyQt5.QtCore import QUrl, QObject
from PyQt5.QtWidgets import QApplication, QListView
from PyQt5.QtQuick import QQuickView, QQuickItem
class MyView(QQuickView):
def __init__(self, parent=None):
super().__init__(parent)
# Load the QML scene from file
self.setSource(QUrl('List.qml'))
#connect signal and source
list = self.rootObject().findChild(QQuickItem, 'myList')
list.mySignal.connect(self.mySlot)
def mySlot(self, index):
print(index)
# Main Function
if __name__ == '__main__':
# Create main app
app = QApplication(sys.argv)
# Create QML view
view = MyView()
view.show()
# Execute the application and exit
sys.exit(app.exec_())
List.qml:
import QtQuick 2.0
import QtQuick.Window 2.2
Item {
width: 500
height: 500
ListView {
anchors.fill: parent
id: list
objectName: "myList"
signal mySignal(int index)
delegate: Item {
width: parent.width * 0.8
height: 40
Row {
id: row1
Rectangle {
width: 40
height: 40
color: colorCode
MouseArea{
anchors.fill: parent
onClicked: list.mySignal(index)
}
}
Text {
text: name
font.bold: true
anchors.verticalCenter: parent.verticalCenter
}
spacing: 10
}
}
model: ListModel {
ListElement {
name: "Grey"
colorCode: "grey"
}
ListElement {
name: "Red"
colorCode: "red"
}
ListElement {
name: "Blue"
colorCode: "blue"
}
ListElement {
name: "Green"
colorCode: "green"
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With