定期重绘QQuickItem

时间:2013-10-18 17:21:27

标签: c++ qt qml

我通过扩展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;
}

1 个答案:

答案 0 :(得分:5)

来自updatePaintNode的文档:

  

如果用户在项目上设置了QQuickItem::update()标记,则QQuickItem::ItemHasContents会调用该函数。

你需要做两件事:定期调用update()并设置标志。这就是它的全部内容。

如果您需要update()的刻度来源,您需要QQuickWindow::frameSwapped()或类似的信号。每帧都会发出这种情况,而且恰好是每一帧。所以,这可行:

QSGNode * myNode = ...;

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