自定义 QQuickItem 未绘制

Posted

技术标签:

【中文标题】自定义 QQuickItem 未绘制【英文标题】:Custom QQuickItem is not painted 【发布时间】:2021-07-11 15:27:31 【问题描述】:

我正在尝试编写自己的 QQuickItems,它使用 SceneGraph 来绘制形状,就好像它的父项是画布一样。我正在使用 PySide6 和 Python。在我的尝试中,我发现了 PySide6 中的一个错误,这是之前报告的。我下载了修复它的补丁,现在似乎可以了(https://bugreports.qt.io/browse/PYSIDE-1345)。

我的程序现在编译并运行,但节点没有绘制。如果我正确理解了文档,我需要做三件事来绘制自定义 QQuickItem:

    从 QQuickItem 继承 覆盖 updatePaintNode 设置 ItemHasContents 标志

我做了所有这些,注册了我的类型,将它添加到 QML 中并确保它具有非零维度。不幸的是,它仍然没有得到回报。我不知道下一步该做什么。

这是最小的工作示例: main.py

# 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


class JustItem(QQuickItem):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setFlag(QQuickItem.ItemHasContents)

    def updatePaintNode(self, node, update_data):
        if node is None:
            node = QSGGeometryNode()

        geometry = QSGGeometry(QSGGeometry.defaultAttributes_Point2D(), 4)
        geometry.setDrawingMode(QSGGeometry.DrawTriangles)
        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)

        material = QSGFlatColorMaterial()
        material.setColor(QColor(255, 0, 0, 127))

        node.setGeometry(geometry)
        node.setMaterial(material)

        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())

QML:

import QtQuick
import QtQuick.Window
import PythonTypes 1.0

Window 
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    JustItem 

    


结果是一个空白的窗口。当我调整它的大小时,它会出现段错误。

【问题讨论】:

至少您必须设置项目大小。您是否尝试使用调试器来定位错误? 您至少需要为您的项目指定宽度和高度。或者使用锚来填充父级。 我都试过了。宽度和高度不会改变这种情况。 anchors.fill 导致程序立即冻结然后段错误 我使用 anchors.fill 变体运行调试器。我可以看到 JustItem 是 Window 的子项,并继承了它的宽度和高度。如果我在调试器中前进,它会出现段错误。 【参考方案1】:

这是 PySide 2 中的一个错误。目前无法在 PySide 2 中绘制自定义 QQuickItems。

这里更详细地讨论了这个错误:https://forum.qt.io/topic/116585/qsggeometry-does-not-work-on-pyside2/16

还有一份错误报告,其中提出了修复建议。修复导致分段错误:https://bugreports.qt.io/browse/PYSIDE-1345

不幸的是,如果你想绘制自定义 QQuickItems,你要么需要用 C++ 编写它们,要么完全使用另一个 GUI 框架。

【讨论】:

以上是关于自定义 QQuickItem 未绘制的主要内容,如果未能解决你的问题,请参考以下文章

在 QQuickItem 中绘制不同颜色的多个点

将背景图像添加到 QQuickItem

定期重绘 QQuickItem

有效地从 QPaintDevice 到 QQuickItem 中的 QSGTexture

自定义绘制下拉框

DotSpatial 自定义MapFunction_mapMain中绘制线(未添加到图层中)