setContextProperty() 不会在 qml 文件中创建类实例
Posted
技术标签:
【中文标题】setContextProperty() 不会在 qml 文件中创建类实例【英文标题】:setContextProperty() doesn't create the class instance inside the qml file 【发布时间】:2020-12-05 06:23:25 【问题描述】:main.py
文件显示一个选项卡小部件。在每个选项卡上,我加载了一个特定的 qml 文件,但为了这个问题,我将只考虑一个 qml 文件和一个选项卡:
import sys, os, math
import numpy as np
from PyQt5 import *
class Tab(QFrame):
def __init__(self):
super().__init__()
self.setGeometry(600, 600, 600, 600)
self.setWindowTitle("PyQt5 Tab Widget")
vbox = QVBoxLayout()
tabWidget = QTabWidget()
tabWidget.addTab(Example01(), "Ex1")
vbox.addWidget(tabWidget)
self.setLayout(vbox)
class GG(QObject):
polygonsChanged = pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent)
self._polygons = []
def get_polygons(self):
return self._polygons
def set_polygons(self, polygons):
self._polygons = polygons
self.polygonsChanged.emit()
polygons = pyqtProperty(
"QVariant", fget=get_polygons, fset=set_polygons,
notify=polygonsChanged
)
class Example01(QWidget):
def __init__(self):
super().__init__()
vbox = QVBoxLayout(self)
vbox.setContentsMargins(0, 0, 0, 0)
numpy_arrays = np.array(
[[[100, 100], [150, 200], [50, 300]],
[[50, 60], [160, 10], [400, 0]]]
)
polygons = []
for ps in numpy_arrays:
polygon = []
for p in ps:
e = QPointF(*p)
polygon.append(e)
polygons.append(polygon)
gg = GG()
gg.polygons = polygons
print(gg.polygons)
ROOT_DIR = os.path.realpath(os.path.dirname(sys.argv[0]))
# print(ROOT_DIR)
qml = os.path.join(ROOT_DIR, "QML Files", "Demo01.qml")
view = QQuickWidget()
view.setSource(QUrl.fromLocalFile(qml))
view.rootContext().setContextProperty("gg", gg)
view.setResizeMode(QQuickWidget.SizeRootObjectToView)
# widget = QWidget.createWindowContainer(view)
# vbox.addWidget(widget)
vbox.addWidget(view)
if __name__ == "__main__":
App = QApplication(sys.argv)
tabDialog = Tab()
tabDialog.show()
App.exec()
现在是 Demo01.qml 文件:
import QtQuick 2.14
import QtQuick.Window 2.14
import QtGraphicalEffects 1.0
Rectangle
id: rect
visible: true
anchors.fill: parent
LinearGradient
anchors.fill: parent
//setting gradient at 45 degrees
start: Qt.point(rect.width, 0)
end: Qt.point(0, rect.height)
gradient: Gradient
GradientStop position: 0.0; color: "#ee9d9d"
GradientStop position: 1.0; color: "#950707"
Canvas
id: drawingCanvas
anchors.fill: parent
onPaint:
var ctx = getContext("2d")
ctx.lineWidth = 5;
ctx.strokeStyle = "red"
console.log(gg)
for(var i in gg.polygons)
var polygon = gg.polygons[i]
ctx.beginPath()
for(var j in polygon)
var p = polygon[j]
if(j === 0)
ctx.moveTo(p.x, p.y)
else
ctx.lineTo(p.x, p.y)
ctx.closePath()
ctx.stroke()
Connections
target: gg
function onPolygonsChanged() drawingCanvas.requestPaint()
问题是没有实例化qml文件里面的gg
,声称gg
对象为null。所以不在我的画布上画任何东西。
我尝试使用 QQuickWidget
和 QQuickView
并得到相同的 null 结果。
如您所见,qml 页面加载到 Tab 窗口没有任何问题。
如果不适用于上述两个元素,如何设置上下文。
【问题讨论】:
【参考方案1】:您的问题有 2 个错误:
您必须在加载 .qml 之前设置上下文属性。 “gg”是一个局部变量,一旦构造函数执行完毕就被销毁,所以在qml中它会为null,解决方案是延长生命周期,例如将其作为类的属性。李>class Example01(QWidget):
def __init__(self):
super().__init__()
numpy_arrays = np.array(
[[[100, 100], [150, 200], [50, 300]], [[50, 60], [160, 10], [400, 0]]]
)
polygons = []
for ps in numpy_arrays:
polygon = []
for p in ps:
e = QPointF(*p)
polygon.append(e)
polygons.append(polygon)
self.gg = GG()
self.gg.polygons = polygons
ROOT_DIR = os.path.realpath(os.path.dirname(sys.argv[0]))
qml = os.path.join(ROOT_DIR, "QML Files", "Demo01.qml")
view = QQuickWidget()
view.rootContext().setContextProperty("gg", self.gg)
view.setSource(QUrl.fromLocalFile(qml))
view.setResizeMode(QQuickWidget.SizeRootObjectToView)
vbox = QVBoxLayout(self)
vbox.setContentsMargins(0, 0, 0, 0)
vbox.addWidget(view)
【讨论】:
谢谢。您的解决方案有效。我会认为这个问题已经结束。以上是关于setContextProperty() 不会在 qml 文件中创建类实例的主要内容,如果未能解决你的问题,请参考以下文章
如何将 QVariant::fromValue 与 QString 一起使用?
Pyside2:使用属性更新 QML TableView 模型