定期重绘 QQuickItem

Posted

技术标签:

【中文标题】定期重绘 QQuickItem【英文标题】:Periodically redraw QQuickItem 【发布时间】:2013-10-18 17:21:26 【问题描述】:

我通过扩展 QQuickItem 并覆盖 updatePaintNode() 函数创建了一个自定义 QML 元素。

由于我需要沿着实时增长的时间线绘制矩形,因此我需要为每个新帧重新绘制 GUI。

有没有办法让 updatePaintNode() 函数为每个新帧定期执行?

我尝试调用node->markDirty(QSGNode::DirtyForceUpdate),但不会导致定期调用 updatePaintNode() 函数。

编辑:这就是我的代码的样子:

QSGNode *PianoRoll::updatePaintNode(QSGNode *n, QQuickItem::UpdatePaintNodeData *data)

    QSGGeometryNode *node = static_cast<QSGGeometryNode *>(n);
    if (!node)
    
        node = new QSGSimpleRectNode(boundingRect(), Qt::white);
    

    node->removeAllChildNodes();

    qreal msPerScreen = 10000;
    qreal pitchesPerScreen = 128;
    qreal x_factor = (qreal) boundingRect().width() / msPerScreen;
    qreal y_factor = (qreal) boundingRect().height() / pitchesPerScreen;

    for (unsigned int i = 0; i < m_stream->notes.size(); i++)
    
        shared_ptr<Note> note = m_stream->notes.at(i);
        qreal left = boundingRect().left() + note->getTime() * x_factor;
        qreal top = boundingRect().top() + note->getPitch() * y_factor;
        qreal width;
        qreal height = y_factor;

        if (note->getDuration() != 0)
        
            width = note->getDuration() * x_factor;
        
        else
        
            // TODO
            width = 500 * x_factor;

        

        QRectF noteRectangle = QRectF(left, top, width, height);
        node->appendChildNode(new QSGSimpleRectNode(noteRectangle, Qt::black));
    
    node->markDirty(QSGNode::DirtyForceUpdate);
    return node;

【问题讨论】:

你一定是做错了什么,确保代码在正确的节点上运行。它应该可以工作。/ 我在帖子中添加了我的代码,也许你能帮帮我! 您需要设置 QQuickItem::ItemHasContents。您是否创建了一个定期调用 update() 的计时器? 【参考方案1】:

来自updatePaintNode的文档:

如果用户在项目上设置了QQuickItem::ItemHasContents 标志,则调用函数作为QQuickItem::update() 的结果。

您需要同时做两件事:定期调用update(),并设置标志。仅此而已。

如果您需要update() 的报价来源,您需要QQuickWindow::frameSwapped() 或类似的信号。这会在每一帧都发出,而且准确地说是每一帧。所以,这会起作用:

QSGNode * myNode = ...;

QObject::connect(window, &QQuickWindow::frameSwapped, [=]() myNode->update(); );

【讨论】:

设置一个计时器每隔几秒调用一次 update() 对我来说似乎很容易出现问题,这就是为什么我假设有一种机制来处理流体重绘(即自动调用 update永远绘制的帧)。 奇怪的是,这个“frameSwapped”信号对我不起作用。当我的应用程序启动时,它会发出一次,场景被绘制,然后不再调用“更新”。 如果我手动调用 update 也不起作用,我只是看不到任何效果,尽管我将 ItemHasContents 设置为 true。 在最近的 Qt 中,如果对场景没有什么可做的,他们可能已经优化了帧交换。您可以调查在updatePaintNode() 中调用update() 是否可以解决问题。也许它只会在 next 框架中更新 - 正是你想要的。 qtdeclarative/src/quick/scenegraph/qsgthreadedrenderloop.cpp的源代码中有一个字符串:“只能从GUI线程或QQuickItem::updatePaintNode()安排更新”。

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

如何使用 python 的 matplotlib 重绘图像?

android涂鸦工具,笔刷的定义,撤销与重绘

css 重绘/重绘oraz reflow

QT 重绘/重绘/更新/做某事

Web前端性能优化-重绘与回流

Qt重绘机制