2016-07-14 12 views
6

Ich möchte das activated Signal von einem QMLListView zu einem pyqtSlot dekoriert Verfahren von meinem Python3/PyQt5 (5.6) Code verbinden.Wie kann PyQt5 pyqtSlot mit dem QML ListView Signal "activated" verbunden werden?

Mein aktueller Ansatz ist das Laden der QML-Szene in meinem Code durch QQmlApplicationEngine und dann findChild(), um einen Verweis auf meine ListView zu erhalten. Das Problem ist, dass ich das ListView nur finden kann, wenn ich nach einem QObject wie findChild(QObject, 'myList') suche. Aber dieses Objekt gibt mir keinen Zugriff auf das Signal activated, höchstwahrscheinlich, weil dieses Signal nur für QAbstractItemView und seine Nachkommen definiert ist.

Also, wenn ich findChild(QListView, 'myList') versuche, ist das Ergebnis None. Deshalb kann ich nicht auf das activated Signal zugreifen. Ist das ein Fehler in PyQt5 oder gibt es eine andere Möglichkeit, sich mit diesem Signal zu verbinden?

Hier ist ein minimales Arbeitsbeispiel.

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" 
     } 
    } 
    } 

} 

Antwort

1

können Sie tun, indem QQuickView statt QQmlApplicationEngine verwenden.

Ich änderte Ihr Python-Skript, um eine neue Klasse hinzuzufügen, die von QQuickView erbt, und fügte ein Signal zum QML-Objekt namens "myList" hinzu.

Darüber hinaus entfernte ich in der QML den Window Typ für Item Typ (Sie können Window mit QQuickView nicht verwenden). Wenn Sie Ihre Anwendung im Vollbildmodus anzeigen möchten, müssen Sie sie in der Klasse MyView angeben. Wenn Sie im Beispiel auf eines der farbigen Rechtecke klicken, wird der Index in der Konsole angezeigt.

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" 
     } 
    } 
    } 

}