如何将PyQt5 pyqtSlot连接到QML ListView信号"激活"?

时间:2016-07-14 06:53:19

标签: python-3.x listview qml pyqt5 qqmlapplicationengine

我想将 QML activated中的ListView信号与 Python3 / PyQt5 pyqtSlot修饰方法相关联>(5.6)代码。

我目前的方法是通过QQmlApplicationEngine在我的代码中加载QML场景,然后使用findChild()获取对ListView的引用。

问题是,我只能在搜索像findChild(QObject, 'myList')这样的QObject时找到ListView。但是htis对象不允许我访问activated信号,很可能是因为此信号仅为QAbstractItemView及其后代定义。

因此,如果我尝试findChild(QListView, 'myList'),结果为None。因此,我无法获得activated信号。这是PyQt5中的一个错误还是我有另一种方式连接到这个信号?

这是一些最小的工作示例。

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

}

1 个答案:

答案 0 :(得分:2)

您可以使用QQuickView代替QQmlApplicationEngine来完成此操作。

我更改了你的python脚本,添加了一个继承自QQuickView的新类,并向名为“myList”的QML对象添加了一个信号。

此外,在QML中,我删除了Window类型的Item类型(您不能将WindowQQuickView一起使用)。如果要全屏显示应用程序,则必须将其指定为MyView类。 在该示例中,如果单击其中一个彩色矩形,索引将显示在控制台中。

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

}