QSGGeometry does not work on PySide2
-
I am trying to use QSGGeometry from PySide2. In the C++ implementation vertexDataAsPoint2D() return a pointer to the 2d points. Not sure how to access the points from geometry.vertexDataAsPoint2D() in PySide2. In PyQt, the following works,
vertices = geometry.vertexDataAsPoint2D() vertices[1].set(x2, y2)
But in PySide2 this gives an error,
TypeError: 'PySide2.QtQuick.QSGGeometry.Point2D' object is not subscriptable -
Hi and welcome to devnet,
From the error it seems that you directly get a Point2D object.
Check the type of the return value of that method.
-
@SGaist , you are right, vertexDataAsPoint2D() returns Point2D. Not sure how this works with PyQt and not on PySide2. From the documentation I understand this function should return a pointer. But pointer in python?
-
@SGaist , you are right, vertexDataAsPoint2D() returns Point2D. Not sure how this works with PyQt and not on PySide2. From the documentation I understand this function should return a pointer. But pointer in python?
@Advig it's a binding issue. You should check the bug report system to see if there's already something related. If not please open a new issue. The best would be if you can provided a minimal project that shows the issue.
-
@Advig it's a binding issue. You should check the bug report system to see if there's already something related. If not please open a new issue. The best would be if you can provided a minimal project that shows the issue.
@SGaist
Thanks. Please find attached the file. Also creating a bug report as advised.
trying to create Scene Graph - Custom Geometry (https://doc.qt.io/qt-5/qtquick-scenegraph-customgeometry-example.html) in Pyside2, but getting following error :
File "/BezierCurveProj/main.py", line 119, in updatePaintNode
vertices[i].set(x, y)
TypeError: 'PySide2.QtQuick.QSGGeometry.Point2D' object is not subscriptable# This Python file uses the following encoding: utf-8 import sys from PySide2.QtWidgets import QApplication from PySide2.QtQuick import QQuickView, QQuickItem, QSGNode, QSGGeometryNode, QSGGeometry, QSGMaterialType from PySide2.QtCore import Signal, QUrl, Property, QPointF from PySide2.QtGui import QColor from PySide2.QtQml import qmlRegisterType class BezierCurve(QQuickItem): def __init__(self): QQuickItem.__init__(self) self.m_p1 = QPointF(0, 0) self.m_p2 = QPointF(0, 1) self.m_p3 = QPointF(1, 0) self.m_p4 = QPointF(1, 1) self.m_segmentCount = 32 self.node = None self.geometry = None self.setFlag(QQuickItem.ItemHasContents, True) @Signal def p1Changed(self): pass @Signal def p2Changed(self): pass @Signal def p3Changed(self): pass @Signal def p4Changed(self): pass @Signal def segmentCountChanged(self): pass def p1(self): return self.m_p1 def p2(self): return self.m_p2 def p3(self): return self.m_p3 def p4(self): return self.m_p4 def segmentCount(self): return self.m_segmentCount def setP1(self, p): if (p == self.m_p1): return self.m_p1 = p self.p1Changed.emit() self.update() def setP2(self, p): if (p == self.m_p2): return self.m_p2 = p self.p2Changed.emit() self.update() def setP3(self, p): if (p == self.m_p3): return self.m_p3 = p self.p3Changed.emit() self.update() def setP4(self, p): if (p == self.m_p4): return self.m_p4 = p self.p4Changed.emit() self.update() def setSegmentCount(self, p): if (p == self.m_segmentCount): return self.m_segmentCount = p self.segmentCountChanged.emit() self.update() def updatePaintNode(self, oldNode, updatePaintNodeData): self.node = oldNode if(self.node is None): self.node = QSGGeometryNode() self.geometry = QSGGeometry(QSGGeometry.defaultAttributes_Point2D(), self.m_segmentCount) self.geometry.setLineWidth(2) self.geometry.setDrawingMode(QSGGeometry.DrawLineStrip) self.node.setGeometry(self.geometry) self.node.setFlag = QSGNode.OwnsGeometry material = QSGMaterialType() material.setColor = QColor(255, 0, 0) self.node.setMaterial = material self.node.setFlag = QSGNode.OwnsMaterial self.geometry.allocate(self.m_segmentCount) else: self.geometry = self.node.geometry() self.geometry.allocate(self.m_segmentCount) itemSize = self.size() vertices = self.geometry.vertexDataAsPoint2D() for i in range(self.m_segmentCount): t = i / (self.m_segmentCount - 1) invt = 1 - t pos = (invt * invt * invt * self.m_p1) + (3 * invt * invt * t * self.m_p2) + (3 * invt * t * t * self.m_p3) + (t * t * t * self.m_p4) x = pos.x() * itemSize.width() y = pos.y() * itemSize.height() vertices[i].set(x, y) self.node.markDirty(QSGNode.DirtyGeometry) return self.node p1 = Property('QPointF', p1, setP1, notify=p1Changed) p2 = Property('QPointF', p2, setP2, notify=p2Changed) p3 = Property('QPointF', p3, setP3, notify=p3Changed) p4 = Property('QPointF', p4, setP4, notify=p4Changed) segmentCount = Property('int', segmentCount, setSegmentCount, notify=segmentCountChanged) if __name__ == "__main__": app = QApplication([]) view = QQuickView() view.setResizeMode(QQuickView.SizeRootObjectToView) qmlRegisterType(BezierCurve, 'BezierCurve', 1, 0, 'BezierCurve') url = QUrl("main.qml") view.setSource(url) view.show() sys.exit(app.exec_())
-
Did you open an issue on the bug tracker ?
-
Thank you !
-
Quick update. I reviewed the ticket again and realized there is a patch there. I recomplied PySide6 with the patch applied and I can say that vertexDataAsPoint2D() now does return a list of Point2D instead of just Point2D. In the ticket the developer states that the fix crashes submitted example. I am yet to confirm whether this causes any issues on my side.
-
Thanks for the feedback !
Can you upload your minimal example on the report ?
It can help fix this issue as well. -
Hi SGaist,
Here's the code. It's really basic:
# This Python file uses the following encoding: utf-8 import os from pathlib import Path import sys from PySide6.QtGui import QGuiApplication, QColor from PySide6.QtQml import QQmlApplicationEngine, qmlRegisterType from PySide6.QtQuick import QQuickItem, QSGGeometryNode, QSGGeometry, QSGFlatColorMaterial, QSGNode class JustItem(QQuickItem): def __init__(self, parent=None): super().__init__(parent) self.setFlag(QQuickItem.ItemHasContents, enabled=True) def updatePaintNode(self, node, update_data): if node is None: node = QSGGeometryNode() geometry = QSGGeometry(QSGGeometry.defaultAttributes_Point2D(), 4) geometry.setLineWidth(1) geometry.setDrawingMode(QSGGeometry.DrawTriangles) material = QSGFlatColorMaterial() material.setColor(QColor(255, 0, 0, 127)) node.setGeometry(geometry) node.setMaterial(material) node.setFlag(QSGNode.OwnsGeometry) node.setFlag(QSGNode.OwnsMaterial) else: geometry = node vertex_data = geometry.vertexDataAsPoint2D() vertex_data[0].set(10, 10) vertex_data[1].set(100, 10) vertex_data[2].set(100, 100) vertex_data[3].set(10, 100) node.markDirty(QSGNode.DirtyGeometry) return node if __name__ == "__main__": qmlRegisterType(JustItem, "PythonTypes", 1, 0, "JustItem") app = QGuiApplication(sys.argv) engine = QQmlApplicationEngine() engine.load(os.fspath(Path(__file__).resolve().parent / "main.qml")) if not engine.rootObjects(): sys.exit(-1) sys.exit(app.exec())
and main.qml:
import QtQuick import QtQuick.Window import PythonTypes 1.0 Window { width: 640 height: 480 visible: true title: qsTr("Hello World") JustItem { } }
If you run it without the patch, it will complain that Point2D is not subscriptible (because Point2D and not a list of Point2Ds is returned). If you run it with the patch applied, it will segfault.
-
Thanks for posting it here but you should add it to the bug report as well. It will be easier to find over there.