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

Python 如何将动态创建的qmlcomponent对象绑定到另一个动态创建的qmlcomponent对象的属性?,python,qt,pyqt,qml,pyqt5,Python,Qt,Pyqt,Qml,Pyqt5,我在一个模块中有两个qml组件 components |- Edge.qml |- Class.qml |- qmdir main |- main.qml main.py 使用main.qml 和qmdir 我正在pythonmain.py文件中加载这两个文件 from PyQt5.QtGui import QGuiApplication, QColor, QSurfaceFormat from PyQt5.QtQml import QQmlApplicationEngine,

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

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

qmdir

我正在pythonmain.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_())
但是现在我想把边E的第一点连接到类组件a,把边E的第二点连接到类组件B

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))
}
为此,我在Edge.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

在我的main.py中,我有一个
classes
列表,其中列出了所有生成的类组件,但是尝试通过Edge(line)将第一个类与第二个类连接起来是行不通的:

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

但是,如果我在main.qml文件中创建两个id为rect1和rect2的矩形。使用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
    }
}

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

解决方案是建立属性
锚1
锚2
var
的数据类型

Edge.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
导入以识别main.qml中的应用程序窗口:

import QtQuick.Controls 1.4

import urmelgraph.components 1.0

import CustomGeometry 1.0

ApplicationWindow {
    visible: true
    width: 640
    height: 240
    title: qsTr("Test")
    color: "#2C3E50"
}

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

Edge.qml和Class.qml是什么?使用“property Class anchor1”,您正在创建一个变量,该变量将存储类型为“Class”的对象,因此anchor2。某些属性将抛出错误,请提供一个合理的答案。Edge.qml是直线类的包装器。qml只是一个qml组件。有文字。2类组件应连接到一个边缘。
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))
}
import QtQuick.Controls 1.4

import urmelgraph.components 1.0

import CustomGeometry 1.0

ApplicationWindow {
    visible: true
    width: 640
    height: 240
    title: qsTr("Test")
    color: "#2C3E50"
}