无法引用来自 python 的现有 QML 元素

Can't reference existing QML elements from python

我不从 python 动态创建元素,我只是想访问已在 qml 文件中声明的现有元素。

我使用 findChild 获取 QObject 引用并连接到信号。这工作正常,但是当我尝试更具体并获得像 QComboBox 这样的小部件(而不是 QObject)时,我总是得到 None。我是不是遗漏了什么或者 findChild 不适合与小部件一起使用?

这是我的简单 qml 代码:

Window {
    visible:true
    width:600
    height:400

    Button {
        id: clickMe
        objectName: "clickMe"
        x: 244
        y: 263
        text: qsTr("click me!")
    }
   ComboBox {
       id: comboBox
       objectName: "comboBox"
       x: 199
       y: 157
       width: 200
   }
}

这是我的 python 代码:

# qt imports
from PyQt5.QtQml import QQmlApplicationEngine
from PyQt5.QtWidgets import QApplication, QWidget, QInputDialog, QLineEdit, QMessageBox
from PyQt5.QtWidgets import QComboBox, QPushButton
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import QObject

app = QApplication(sys.argv)
engine = QQmlApplicationEngine()
engine.load('main.qml')
win = engine.rootObjects()[0]
win.show()


# this does work because it is QObject:
clickMe = win.findChild(QObject, "clickMe")
clickMe.clicked.connect(Foo)

# this does not work, I get None so can't add items to the combobox:
comboBox = win.findChild(QComboBox, "comboBox")
comboBox.addItem("a")


sys.exit(app.exec_())

首先,QML Item Combobox 不是 QtWidgets QComboBox,因此您不应使用它进行过滤 class,这就是您尝试失败的原因。从 python(或 C++)访问 QML 元素也是不好的做法,因为生命周期不受管理(例如,可以删除和重新创建相同“id”的对象而不通知),而必须创建 QObject允许交换信息,例如对于 QComboBox 你可以创建一个模型:

main.py

import os
import sys

# qt imports
from PyQt5.QtCore import pyqtProperty, pyqtSlot, QObject, QUrl
from PyQt5.QtGui import QGuiApplication, QStandardItem, QStandardItemModel
from PyQt5.QtQml import QQmlApplicationEngine

CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))


class Manager(QObject):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._model = QStandardItemModel()

    @pyqtProperty(QObject, constant=True)
    def model(self):
        return self._model

    @pyqtSlot()
    def foo(self):
        print("clicked")


def main():
    app = QGuiApplication(sys.argv)

    manager = Manager()

    engine = QQmlApplicationEngine()
    engine.rootContext().setContextProperty("manager", manager)

    filename = os.path.join(CURRENT_DIR, "main.qml")

    engine.load(QUrl.fromLocalFile(filename))

    item = QStandardItem("a")
    manager.model.appendRow(item)

    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

main.qml

import QtQuick.Window 2.15
import QtQuick.Controls 2.15


Window {
    visible:true
    width:600
    height:400

    Button {
        id: clickMe
        x: 244
        y: 263
        text: qsTr("click me!")
        onClicked: manager.foo()
    }
   ComboBox {
       id: comboBox
       x: 199
       y: 157
       width: 200
       model: manager.model
       textRole: "display"
   }
}

我建议您也阅读我的其他回答: