无法引用来自 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"
}
}
我建议您也阅读我的其他回答:
我不从 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"
}
}
我建议您也阅读我的其他回答: