Python动态实例化QML组件



我想使用Python将自定义组件动态添加到我的view.qml中,但我不确定我的方法,因为我在结果窗口中看不到Button.qml组件。理想情况下,我希望能够在ColumnLayout中实例化几行按钮。顺便说一句,Button.qml自定义快速示例/演示按钮的源代码我也包含在下面。它不是PySide6库中的QtQuick Button.qml

我以为我可以从view.qml调用函数,但显然不行?我看到了另一种涉及使用单独Javascript文件的方法,但如果可能的话,我希望避免这样做。

主要.py

import os
from pathlib import Path
import sys
from PySide6.QtCore import  QUrl, QObject
from PySide6.QtGui import QGuiApplication
from PySide6.QtQuick import QQuickView
class CreateWidgets(QObject):

def instantiate_widgets(self, root, widgetsNeeded):
#for i in widgetsNeeded:
root.doSomething

if __name__ == '__main__':
app = QGuiApplication(sys.argv)
view = QQuickView()
view.setResizeMode(QQuickView.SizeRootObjectToView);
qml_file = os.fspath(Path(__file__).resolve().parent / 'view.qml')
view.setSource(QUrl.fromLocalFile(qml_file))
if view.status() == QQuickView.Error:
sys.exit(-1)

root = view.rootObject()
widgetCreator = CreateWidgets()
widgetCreator.instantiate_widgets(root, 6)

view.show()
res = app.exec()
# Deleting the view before it goes out of scope is required to make sure all child QML instances
# are destroyed in the correct order.
del view
sys.exit(res)

view.qml

import QtQuick 2.0
import QtQuick.Layouts 1.12
Item{
function doSomething(){
var component = Qt.createComponent("Button.qml");
if (component.status === Component.Ready) {
var button = component.createObject(colLayout);
button.color = "red";
}
console.log("Button created");
}
ColumnLayout{
id: colLayout
Rectangle {
id: page           
width: 500; height: 200
color: "lightgray"  
}   
}
}

Button.qml

import QtQuick 2.0
Rectangle { width: 80; height: 50; color: "red"; anchors.fill: parent}

(评论部分的问题代码参考(

Main.py
import os
import random
import sys
from pathlib import Path
from PySide6.QtCore import Property, QUrl, QObject, Qt
from PySide6.QtGui import QColor, QGuiApplication, QStandardItem, QStandardItemModel
from PySide6.QtQuick import QQuickView
ColorRole = Qt.UserRole
BorderRole = Qt.UserRole
class Manager(QObject):
def __init__(self, parent=None):
super().__init__(parent)
self._model = QStandardItemModel()
self._model.setItemRoleNames({Qt.DisplayRole: b"display", ColorRole: b"custom", BorderRole: b"custom2"})
@Property(QObject, constant=True)
def model(self):
return self._model
def add_button(self, text, color, bColor):
item = QStandardItem(text)
item.setData(color, ColorRole)
item.setData(bColor, BorderRole)
self._model.appendRow(item)

if __name__ == "__main__":
app = QGuiApplication(sys.argv)
manager = Manager()
view = QQuickView()
view.rootContext().setContextProperty("manager", manager)
view.setResizeMode(QQuickView.SizeRootObjectToView)
qml_file = os.fspath(Path(__file__).resolve().parent / "view.qml")
view.setSource(QUrl.fromLocalFile(qml_file))
if view.status() == QQuickView.Error:
sys.exit(-1)
for i in range(6):
color = QColor(*random.sample(range(0, 255), 3))
border = QColor(*random.sample(range(0, 255), 3))
manager.add_button(f"button-{i}", color, border)
view.show()
res = app.exec()
sys.exit(res)

View.qml

import QtQuick 2.0
import QtQuick.Layouts 1.12
Item {
ColumnLayout {
id: colLayout
anchors.fill: parent
Repeater{
model: manager.model
Button{
color: model.custom
text: model.display
border.color: model.custom2
}
}
}
}

Button.qml

import QtQuick 2.0
Rectangle {
id: root
property alias text: txt.text
width: 80
height: 50
color: "red"
border.color: "black"
Text{
id: txt
anchors.centerIn: parent
}
}

其思想是Python(或C++(向QML提供信息以创建项目,例如使用模型和中继器。

另一方面,如果一个项将成为ColumnLayout的子项,则不应使用锚点,因为它们都处理该项的几何图形,因此会发生冲突。

考虑到以上内容,我添加了更多的元素,如可变文本、可变颜色等来演示逻辑。

import os
import random
import sys
from pathlib import Path
from PySide6.QtCore import Property, QUrl, QObject, Qt
from PySide6.QtGui import QColor, QGuiApplication, QStandardItem, QStandardItemModel
from PySide6.QtQuick import QQuickView
ColorRole = Qt.UserRole

class Manager(QObject):
def __init__(self, parent=None):
super().__init__(parent)
self._model = QStandardItemModel()
self._model.setItemRoleNames({Qt.DisplayRole: b"display", ColorRole: b"custom"})
@Property(QObject, constant=True)
def model(self):
return self._model
def add_button(self, text, color):
item = QStandardItem(text)
item.setData(color, ColorRole)
self._model.appendRow(item)

if __name__ == "__main__":
app = QGuiApplication(sys.argv)
manager = Manager()
view = QQuickView()
view.rootContext().setContextProperty("manager", manager)
view.setResizeMode(QQuickView.SizeRootObjectToView)
qml_file = os.fspath(Path(__file__).resolve().parent / "view.qml")
view.setSource(QUrl.fromLocalFile(qml_file))
if view.status() == QQuickView.Error:
sys.exit(-1)
for i in range(6):
color = QColor(*random.sample(range(0, 255), 3))
manager.add_button(f"button-{i}", color)
view.show()
res = app.exec()
sys.exit(res)
import QtQuick 2.0
import QtQuick.Layouts 1.12
Item {
ColumnLayout {
id: colLayout
anchors.fill: parent
Repeater{
model: manager.model
Button{
color: model.custom
text: model.display
}
}
}
}
import QtQuick 2.0
Rectangle {
id: root
property alias text: txt.text
width: 80
height: 50
color: "red"
Text{
id: txt
anchors.centerIn: parent
}
}

更新:

每个角色都必须有不同的数值,否则Qt无法识别它,在您的情况下,您可以更改:

BorderRole = Qt.UserRole + 1

最新更新