如何将动态创建的qmlcomponent对象绑定到另一个动态创建的qmlcomponent对象的属性?

2024-09-28 20:49:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我在一个模块中有两个qml组件。在

components
  |- Edge.qml
  |- Class.qml
  |- qmdir
main
  |- main.qml
main.py

主.qml

^{pr2}$

qmdir

module urmelgraph.components
Class 1.0 Class.qml
Edge 1.0 Edge.qml

我正在我的python中加载这两个主.py文件。在

from PyQt5.QtGui import QGuiApplication, QColor, QSurfaceFormat
from PyQt5.QtQml import QQmlApplicationEngine, QQmlComponent, QQmlContext, qmlRegisterType, QQmlProperty
from PyQt5.QtQuick import QQuickItem, QQuickView, QSGGeometryNode, QSGGeometry, QSGNode, QSGFlatColorMaterial
from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot, pyqtProperty, QUrl, QPointF, QSizeF

from  pathlib import Path

class StraightLine(QQuickItem):
    p1_Changed = pyqtSignal()
    p2_Changed = pyqtSignal()
    segment_count_Changed = pyqtSignal()

    def __init__(self, parent: QQuickItem, p1: QPointF = QPointF(0,0), p2: QPointF = QPointF(1,1), segment_count: int = 2):
        super().__init__(parent)
        self._p1 = p1
        self._p2 = p2
        self._segment_count = segment_count
        self.setFlag(QQuickItem.ItemHasContents, True)

    @pyqtProperty("QPointF", notify = p1_Changed)
    def p1(self):
        return self._p1

    @p1.setter
    def p1(self, p1: QPointF):
        if p1 == self._p1:
            return

        self._p1 = p1
        self.p1_Changed.emit()
        self.update()

    @pyqtProperty("QPointF", notify = p2_Changed)
    def p2(self):
        return self._p2

    @p2.setter
    def p2(self, p2: QPointF):
        if p2 == self._p2:
            return

        self._p2 = p2
        self.p2_Changed.emit()
        self.update()

    @pyqtProperty(int, notify = segment_count_Changed)
    def segment_count(self):
        return self._segment_count

    @segment_count.setter
    def segment_count(self, count: int):
        if count == self._segment_count:
            return

        self._segment_count = count
        self.segment_count_Changed.emit()
        self.update()

    def updatePaintNode(self, oldNode: QSGGeometryNode, _):
        if oldNode == None:
            node = QSGGeometryNode()
            geometry = QSGGeometry(QSGGeometry.defaultAttributes_Point2D(), self._segment_count)
            geometry.setLineWidth(3)
            geometry.setDrawingMode(QSGGeometry.DrawLineStrip)
            node.setGeometry(geometry)
            node.setFlag(QSGNode.OwnsGeometry)

            material = QSGFlatColorMaterial()
            material.setColor(QColor(45, 100, 120))
            node.setMaterial(material)
            node.setFlag(QSGNode.OwnsMaterial)
        else:
            node = oldNode
            geometry = node.geometry()
            geometry.allocate(self._segment_count)

        itemSize = self.size()
        vertices = geometry.vertexDataAsPoint2D()

        x1 = self._p1.x()
        y1 = self._p1.y()
        vertices[0].set(x1, y1)

        x2 = self._p2.x()
        y2 = self._p2.y()
        vertices[1].set(x2, y2)

        print(vertices[1].x)

        node.markDirty(QSGNode.DirtyGeometry)

        return node

if __name__ == "__main__":
    import sys

    path = Path("..")
    resolved_path = path.resolve()

    # Create an instance of the application
    app = QGuiApplication(sys.argv)

    # Set antialising 4 samples
    format = QSurfaceFormat()
    format.setSamples(4)
    QSurfaceFormat.setDefaultFormat(format)

    # register custom types
    qmlRegisterType(StraightLine, "CustomGeometry", 1, 0, "StraightLine")

    # Create QML engine
    engine = QQmlApplicationEngine()

    # Load the qml file into the engine
    engine.addImportPath(str(resolved_path))
    engine.load("main/main.qml")

    # load the components
    component = QQmlComponent(engine)
    component.loadUrl(QUrl("components/Class.qml"))
    line_component = QQmlComponent(engine)
    line_component.loadUrl(QUrl("components/Edge.qml"))
    # check for component creation errors
    for error in component.errors():
        print(error.toString())
    # check for component creation errors
    for error in line_component.errors():
        print(error.toString())

    classes = []
    for index, class_name in enumerate(["Person", "Home"]):
        # create a new instance of the component
        cclass = component.create()
        # set the class name property of the component
        cclass.setProperty("className", class_name)
        cclass.setX((cclass.width() + 50) * index)
        cclass.setParentItem(engine.rootObjects()[0].findChild(QQuickItem))
        classes.append(cclass)

    line = line_component.beginCreate(engine.rootContext())
    line.setProperty("anchor1", classes[0])
    line.setProperty("anchor2", classes[1])
    line_component.completeCreate()

    # check for object creation errors
    for error in line_component.errors():
        print(error.toString())
    for error in component.errors():
        print(error.toString())

    engine.quit.connect(app.quit)
    sys.exit(app.exec_())

但现在我想把边的第一个点连接到类组件a上,边的第二个点连接到类组件B上。在

为此,我在中创建了属性边缘.qml。在

import QtQuick 2.11
import CustomGeometry 1.0
import urmelgraph.components 1.0

StraightLine {
    property Class anchor1
    property Class anchor2

    anchors.fill: parent

    Component.onCompleted: {
        console.log(anchor1)
        console.log(anchor2)
    }

    p2: Qt.point(anchor2.x + (anchor2.width/2), anchor2.y + (anchor2.height/2))
    p1: Qt.point(anchor1.x + (anchor1.width/2), anchor1.y + (anchor1.height/2))
}

这是我的qml

import QtQuick 2.11
import QtQuick.Layouts 1.11

Rectangle {
    width: 50
    height: 20
    color: "#2980B9"

    border.color: "#ECF0F1"

    property string className

    Drag.active: dragArea.drag.active

    MouseArea {
        id: dragArea
        anchors.fill: parent

        drag.target: parent
        // disable delay when moved
        drag.threshold: 0
    }
    Text {
        text: className
    }
}

在我的主.py我有一个包含所有生成类组件的classes列表,但是尝试通过边缘(line)将第一个类与第二个类连接起来是行不通的:

line = line_component.beginCreate(engine.rootContext())
line.setProperty("anchor1", classes[0])
line.setProperty("anchor2", classes[1])
line_component.completeCreate()

但是,如果我在中创建两个id为rect1和rect2的矩形主.qml文件。使用QQuickItem直线,此代码正在工作:

StraightLine {
    anchors.fill: parent

    p1: Qt.point(rect2.x + (rect2.width/2), rect2.y + (rect2.height/2))
    p2: Qt.point(rect1.x + (rect1.width/2), rect1.y + (rect1.height/2))
}

Rectangle {
    id: rect1
    width: 10
    height: 10
    color: "red"
    radius: width*0.5

    Drag.active: dragArea.drag.active

    MouseArea {
        id: dragArea
        anchors.fill: parent

        drag.target: parent
        // disable delay when moved
        drag.threshold: 0
    }
}

Rectangle {
    id: rect2
    width: 10
    height: 10
    color: "blue"
    radius: width*0.5

    Drag.active: dragArea2.drag.active

    MouseArea {
        id: dragArea2
        anchors.fill: parent

        drag.target: parent
        // disable delay when moved
        drag.threshold: 0
    }
}

如何将这些class组件的引用传递给我的edge组件,以正确设置x、y、宽度、高度的绑定?在


Tags: importselfnodecountlinesegmentqmlwidth
1条回答
网友
1楼 · 发布于 2024-09-28 20:49:41

解决方案是建立属性anchor1和{}到{}的数据类型。在

在边缘.qml在

import QtQuick 2.11
import CustomGeometry 1.0

StraightLine {
    property var anchor1
    property var anchor2

    anchors.fill: parent

    Component.onCompleted: {
        console.log(anchor1)
        console.log(anchor2)
    }

    p2: Qt.point(anchor2.x + (anchor2.width/2), anchor2.y + (anchor2.height/2))
    p1: Qt.point(anchor1.x + (anchor1.width/2), anchor1.y + (anchor1.height/2))
}

另一方面,我没有包含QtQuick.Controls 1.4导入来识别qml公司名称:

^{pr2}$

在下面的link中,您将找到完整的代码

相关问题 更多 >