How to connect PyQt5 pyqtSlot to QML ListView signal "activated"?

I would like to connect the activated signal from the QML ListView to the pyqtSlot decorated method from my Python3 / PyQt5 code (5.6).

My current approach is to load a QML scene in my code through QQmlApplicationEngine , and then use findChild() to get a link to my ListView .

The problem is that I can find a ListView when searching for a QObject, for example findChild(QObject, 'myList') . But the htis object does not give me access to the activated signal, most likely because this signal is defined only for QAbstractItemView and its descendants.

So, if I try findChild(QListView, 'myList') , the result will be None . Therefore, I cannot get to the activated signal. Is this a bug in PyQt5 or is there another way to connect to this signal?

Here are some minimal working examples.

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" } } } } 
+6
source share
1 answer

You can do this using QQuickView instead of QQmlApplicationEngine .

I modified your python script to add a new class that inherits from QQuickView , and added a signal to the QML object named "myList".

Also, in QML, I removed the Window type for the Item type (you cannot use Window with QQuickView ). If you want to display the application in full screen mode, you need to specify it in the MyView class. In this 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" } } } } 
+1
source

All Articles