2016-07-14 25 views
6

Chciałbym podłączyć sygnał activated z QMLListView do pyqtSlot zdobione metodą z mojego Python3/PyQt5 (5.6) kodu.Jak podłączyć PyQt5 pyqtSlot do QML ListView sygnał "aktywowany"?

Moje obecne podejście polega na załadowaniu sceny QML w moim kodzie przez QQmlApplicationEngine, a następnie użycie findChild(), aby uzyskać odniesienie do mojego ListView.

Problem polega na tym, że mogę znaleźć ListView tylko podczas wyszukiwania elementu QObject, takiego jak findChild(QObject, 'myList'). Ale obiekt ten nie daje mi dostępu do sygnału activated, najprawdopodobniej dlatego, że ten sygnał jest zdefiniowany tylko dla QAbstractItemView i jego potomków.

Więc jeśli spróbuję findChild(QListView, 'myList'), otrzymam wynik None. Dlatego nie jestem w stanie dotrzeć do sygnału activated. Czy jest to błąd w PyQt5, czy jest inny sposób, aby połączyć się z tym sygnałem?

Oto minimalny przykład działania.

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

} 

Odpowiedz

1

Można to zrobić za pomocą QQuickView zamiast QQmlApplicationEngine.

Zmieniłem skrypt Pythona, aby dodać nową klasę, która dziedziczy po QQuickView, i dodałem sygnał do obiektu QML o nazwie "myList".

Co więcej, w QML usunięto typ Window dla typu Item (nie można używać Window z QQuickView). Jeśli chcesz wyświetlić aplikację na pełnym ekranie, musisz podać ją w klasie MyView. W tym przykładzie kliknięcie jednego z kolorowych prostokątów spowoduje wyświetlenie indeksu w konsoli.

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

}