Я использую 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
отделки. И это не под моим контролем.
Вопрос:
Как я могу убедиться, что 2 указателя material
& child_node
правильно очищены из памяти?
Делает child_node->setFlag(QSGNode::OwnsMaterial)
как я делаю выше, устанавливает владение указателями в QtSceneGraph & освободить меня от бремени удаления указателей?
Вторичный вопрос:
я использую oldNode->removeAllChildNodes()
очистить данные, нарисованные в предыдущем кадре. Это хороший способ очистить предыдущие данные на экране, прежде чем рисовать новые данные?
PS:
Я повторяю: у этой реализации нет проблем с производительностью. Я просто хочу быть уверен, что я не вызываю никаких утечек памяти. Я пытался использовать material
& child_node
как умные указатели вроде так:
auto material = std::make_shared<QSGVertexColorMaterial>();
auto child_node = new std::make_shared<QSGGeometryNode>();
Но это вызывает сбой, когда material
& child_node
автоматически удаляются из памяти на более позднем этапе.
Да, в вашем примере кода вы можете рассчитывать на автоматическую очистку узлов. Вы не пропускаете память из updatePaintNode.
oldnode и child_node
oldnode
возвращаемый из QQuickItem :: updatePaintNode () автоматически удаляется в нужном потоке в нужное время. Деревья экземпляров QSGNode управляются с помощью QSGNode :: OwnedByParent, который устанавливается по умолчанию.
материал
Потому что вы установили флаг QSGNode :: OwnsMaterial для вашего child_node material
удаляется при удалении child_node.
Второй вопрос: Это хороший способ?
Ответ — нет. Нет смысла создавать и удалять узлы каждый раз при рендеринге сцены. Вместо этого вы должны повторно использовать узел / узлы. В приведенном ниже примере кода я предполагаю, что геометрия изменяется, но материал не меняется в течение времени жизни QQuickItem. Если материал изменится, вам может потребоваться позвонить node-> 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;
}
Других решений пока нет …