如何将PyQt5的pyqtSlot连接到QML ListView信号“activated”?

7
我想将一个 QML 的 ListView 中的 activated 信号连接到我的 Python3/PyQt5 (5.6) 代码中使用 pyqtSlot 装饰的方法。目前我的做法是通过 QQmlApplicationEngine 在代码中加载 QML 场景,然后使用 findChild() 获取对我的 ListView 的引用。
问题在于,只有在搜索 QObject 类似于 findChild(QObject, 'myList') 时我才能找到 ListView。但该对象不能让我访问 activated 信号,很可能是因为此信号仅为 QAbstractItemView 及其子类定义。
如果我尝试 findChild(QListView, 'myList'),结果是 None。因此,我无法访问 activated 信号。这是 PyQt5 中的一个 bug 吗?还是说我有另一种方法来连接到此信号?
以下是一些最小工作示例。 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个回答

2

您可以使用QQuickView代替QQmlApplicationEngine来实现这一点。

我修改了您的Python脚本,添加了一个从QQuickView继承的新类,并在QML对象中添加了一个名为“myList”的信号。

此外,在QML中,我将Item类型的Window类型删除(不能在QQuickView中使用Window)。如果您想全屏显示应用程序,则必须在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"
      }
    }
  }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接