【发布时间】:2018-07-26 18:30:12
【问题描述】:
我在一个模块中有两个 qml 组件。
components
|- Edge.qml
|- Class.qml
|- qmdir
main
|- main.qml
main.py
与 main.qml
import urmelgraph.components 1.0
import CustomGeometry 1.0
ApplicationWindow {
visible: true
width: 640
height: 240
title: qsTr("Test")
color: "#2C3E50"
}
和qmdir
module urmelgraph.components
Class 1.0 Class.qml
Edge 1.0 Edge.qml
我正在我的 python main.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 的第一个点连接到 Class 组件 A 和边 E 的第二个点到一个类组件B。
为此,我在 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))
}
这是我的 Class.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
}
}
在我的 main.py 中,我有一个 classes 列表,其中包含所有生成的 Class 组件,但试图通过 Edge(线)连接第一个类和第二个类,例如,不起作用:
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 此代码有效:
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、width、height 的绑定?
【问题讨论】:
-
Edge.qml 和 Class.qml 是什么?
-
用“property Class anchor1”你正在创建一个变量来存储一个“Class”类型的对象,所以anchor2.Some_property会抛出一个错误,请提供一个像样的minimal reproducible example
-
我编辑了我的答案。 Edge.qml 是 StraightLine 类的包装器。 Class.qml 只是一个 qml 组件。带文字。 2 类组件应该连接到一个边缘。