【问题标题】:setContextProperty() doesn't create the class instance inside the qml filesetContextProperty() 不会在 qml 文件中创建类实例
【发布时间】: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。所以不在我的画布上画任何东西。 我尝试使用 QQuickWidgetQQuickView 并得到相同的 null 结果。 如您所见,qml 页面加载到 Tab 窗口没有任何问题。

如果不适用于上述两个元素,如何设置上下文。

【问题讨论】:

    标签: python pyqt5 qml


    【解决方案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)

    【讨论】:

    • 谢谢。您的解决方案有效。我会认为这个问题已经结束。
    猜你喜欢
    • 2019-03-25
    • 1970-01-01
    • 1970-01-01
    • 2014-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多