2016-07-14 61 views
6

Vorrei collegare il segnale activated da un QMLListView a un metodo decorato pyqtSlot dal mio (5.6) Codice python3/PyQt5.Come connettere PyQt5 pyqtSlot al segnale QML ListView "attivato"?

Il mio approccio attuale è caricare la scena QML nel mio codice tramite QQmlApplicationEngine e quindi utilizzare findChild() per ottenere un riferimento al mio ListView.

Il problema è che posso trovare solo il ListView durante la ricerca di un QObject come findChild(QObject, 'myList'). Ma questo oggetto non mi dà accesso al segnale activated, molto probabilmente perché questo segnale è solo definito per QAbstractItemView e discendenti.

Quindi se provo findChild(QListView, 'myList') il risultato è None. Pertanto non sono in grado di raggiungere il segnale activated. Si tratta di un bug in PyQt5 o c'è un altro modo per collegarmi a questo segnale?

Ecco alcuni esempi di funzionamento minimi.

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

} 

risposta

1

È possibile farlo usando QQuickView invece di QQmlApplicationEngine.

Ho modificato lo script python per aggiungere una nuova classe che eredita da QQuickView e aggiunto un segnale all'oggetto QML denominato "myList".

Inoltre, nel QML ho rimosso il tipo Window per il tipo Item (non è possibile utilizzare Window con QQuickView). Se si desidera visualizzare l'applicazione a schermo intero, è necessario specificarla nella classe MyView. Nell'esempio, se si fa clic su uno dei rettangoli colorati, l'indice verrà visualizzato nella 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" 
     } 
    } 
    } 

}