我使用QSGGeometry
,QSGVertexColorMaterial
& QSGGeometryNode
QQuickItem
在我的MyQuickItem
派生类中实时绘制一些内容updatePaintNode
。
以下是我的QSGNode * MyQuickItem::updatePaintNode(QSGNode * oldNode, UpdatePaintNodeData * updatePaintNodeData) {
if (!oldNode) {
oldNode = new QSGNode;
}
oldNode->removeAllChildNodes();
QSGGeometry * geometry = GetMyGeometry();
QSGVertexColorMaterial * material = new QSGVertexColorMaterial;
QSGGeometryNode * child_node = new QSGGeometryNode;
child_node->setGeometry(geometry);
child_node->setMaterial(material);
child_node->setFlag(QSGNode::OwnsMaterial);
oldNode->appendChildNode(child_node);
return oldNode;
}
方法,其中重绘逻辑的关键在于。
updatePaintNode
问题:
上面的逻辑效果很好。完全没有功能问题。也没有性能问题。 但我担心我会导致内存泄漏。请看上面方法QSGVertexColorMaterial * material = new QSGVertexColorMaterial;
QSGGeometryNode * child_node = new QSGGeometryNode;
中的以下两行,我在其中分配原始指针。
updatePaintNode
我分配他们&我不删除它们。这是因为应该删除它们的点是在material
完成之后。 那不受我的控制。
问题:
如何确保2个指针child_node
& child_node->setFlag(QSGNode::OwnsMaterial)
是否已正确清除记忆?
像我上面那样做oldNode->removeAllChildNodes()
会将指针的所有权设置为QtSceneGraph&减轻我删除指针的负担?
次要问题:
我正在使用material
来清除前一帧中绘制的数据。这是在绘制新数据之前清除屏幕上的先前数据的好方法吗?
PS:
我重申:此实现没有性能问题。我只是想确定我没有造成任何内存泄漏。我尝试过使用child_node
&amp; auto material = std::make_shared<QSGVertexColorMaterial>();
auto child_node = new std::make_shared<QSGGeometryNode>();
像智能指针一样:
material
但这会导致child_node
&amp;稍后会从内存中自动清除--**First**---|--Second--|---Third--|--Fourth--| (scrolling categories)
------------------------------------------------------------------
\\\FirstA\\\ \\\FirstB\\\ \\\FirstC\\\ \\\FirstD\\\
\\\FirstA\\\ \\\FirstB\\\ \\\FirstC\\\ \\\FirstD\\\
------------------------------------------------------------------
。
答案 0 :(得分:4)
是的,在您的示例代码中,您可以依赖节点的自动清理。您没有从updatePaintNode泄漏内存。
oldnode和child_node
从QQuickItem :: updatePaintNode()返回的 oldnode
会在正确的时间在右侧线程上自动删除。通过使用默认设置的QSGNode :: OwnedByParent来管理QSGNode实例的树。
<强>材料强>
因为你已经为你的child_node设置了标志QSGNode :: OwnsMaterial {child}删除了child_node时删除了material
。
第二个问题:这是一个好方法吗?
答案是否定的。每次渲染场景时都没有创建和删除节点的意义。相反,您应该重用节点/节点。在下面的示例代码中,我假设几何体发生了变化,但材料在QQuickItem的生命周期内没有变化。如果材料发生变化,您可能需要调用 node-&gt; markDirty(QSGNode :: DirtyMaterial)。请注意,只创建了一个节点,并且只创建了一个节点(除非窗口隐藏,然后再返回到fg或其他位置)。
QSGNode * MyQuickItem::updatePaintNode(QSGNode * oldNode, UpdatePaintNodeData * updatePaintNodeData) {
QSGGeometryNode *node = static_cast<QSGGeometryNode *>(oldNode);
if (!node) {
node = new QSGGeometryNode;
QSGVertexColorMaterial * material = new QSGVertexColorMaterial;
node->setMaterial(material);
node->setFlag(QSGNode::OwnsMaterial);
}
// if GetMyGeometry returns every time a new dynamically allocated object then you should
// call node->setFlag(QSGNode::OwnsGeometry) to not leak memory here:
QSGGeometry * geometry = GetMyGeometry();
node->setGeometry(geometry);
// No need to call node->markDirty(QSGNode::DirtyGeometry) because setGeometry is called.
return node;
}