You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

QQuickPaintedItem在QML Designer中不可见的技术求助

Fix QML Designer Preview for Custom QQuickPaintedItem Component

I get it—having your custom TextBalloon work at runtime but not show up in QML Designer is super frustrating. Let’s break down why this happens and how to fix it quickly.

Why QQuickPaintedItem Fails in Designer

QML Designer uses a Qt Quick Scene Graph-based preview engine, and QQuickPaintedItem relies on software rendering via QPainter. Designer often skips executing custom paint() methods because it doesn’t fully initialize the software drawing context during previews.

The best workaround is to rewrite your component using Qt Quick Scene Graph directly (inheriting QQuickItem instead of QQuickPaintedItem), which Designer supports natively.


Solution 1: Rewrite with QQuickItem and Scene Graph

Here’s how to convert your TextBalloon to use Scene Graph, which will render correctly in both runtime and Designer:

Updated Header File (textballoon.h)

#include <QQuickItem>
#include <QSGNode>

class TextBalloon : public QQuickItem
{
    Q_OBJECT
    Q_PROPERTY(bool rightAligned READ isRightAligned WRITE setRightAligned NOTIFY rightAlignedChanged)
public:
    TextBalloon(QQuickItem *parent = nullptr);
    bool isRightAligned() const;
    void setRightAligned(bool rightAligned);

protected:
    QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override;

signals:
    void rightAlignedChanged();

private:
    bool m_rightAligned = false;
};

Updated Implementation (textballoon.cpp)

#include "textballoon.h"
#include <QSGFlatColorMaterial>
#include <QSGGeometryNode>
#include <QSGGeometry>
#include <cmath>

TextBalloon::TextBalloon(QQuickItem *parent)
    : QQuickItem(parent)
{
    setFlag(ItemHasContents, true); // Required to trigger updatePaintNode
}

bool TextBalloon::isRightAligned() const
{
    return m_rightAligned;
}

void TextBalloon::setRightAligned(bool rightAligned)
{
    if (m_rightAligned == rightAligned)
        return;

    m_rightAligned = rightAligned;
    emit rightAlignedChanged();
    update(); // Tell Scene Graph to refresh the node
}

QSGNode *TextBalloon::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
{
    QSGGeometryNode *node = static_cast<QSGGeometryNode*>(oldNode);
    if (!node) {
        node = new QSGGeometryNode;
        // Set up the green material for the balloon
        QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
        material->setColor(QColor("#007430"));
        node->setMaterial(material);
        node->setFlag(QSGNode::OwnsMaterial);
    }

    const QSizeF itemSize = size();
    const qreal radius = 10;
    const qreal tailHeight = 10;
    QVector<QSGGeometry::Point2D> vertices;

    // Build the rounded rectangle shape
    // Top-left corner arc
    vertices << QSGGeometry::Point2D(radius, 0);
    for (int i = 1; i < 9; ++i) {
        const qreal angle = M_PI_2 * i / 8;
        vertices << QSGGeometry::Point2D(radius - radius * cos(angle), radius * sin(angle));
    }
    // Top edge
    vertices << QSGGeometry::Point2D(itemSize.width() - radius, 0);
    // Top-right corner arc
    for (int i = 1; i < 9; ++i) {
        const qreal angle = M_PI_2 * i / 8;
        vertices << QSGGeometry::Point2D(itemSize.width() - radius * sin(angle), radius - radius * cos(angle));
    }
    // Right edge
    vertices << QSGGeometry::Point2D(itemSize.width(), itemSize.height() - tailHeight - radius);

    // Handle right-aligned vs left-aligned tail
    if (!m_rightAligned) {
        // Bottom-right corner arc (no tail here)
        for (int i = 1; i < 9; ++i) {
            const qreal angle = M_PI_2 * i / 8;
            vertices << QSGGeometry::Point2D(itemSize.width() - radius + radius * cos(angle), itemSize.height() - tailHeight - radius + radius * sin(angle));
        }
        // Bottom edge to tail start
        vertices << QSGGeometry::Point2D(30, itemSize.height() - tailHeight);
        // Left-aligned tail
        vertices << QSGGeometry::Point2D(20, itemSize.height());
        vertices << QSGGeometry::Point2D(10, itemSize.height() - tailHeight);
    } else {
        // Right-aligned tail
        vertices << QSGGeometry::Point2D(itemSize.width() - 10, itemSize.height() - tailHeight);
        vertices << QSGGeometry::Point2D(itemSize.width() - 20, itemSize.height());
        vertices << QSGGeometry::Point2D(itemSize.width() - 30, itemSize.height() - tailHeight);
    }

    // Bottom-left corner arc
    vertices << QSGGeometry::Point2D(radius, itemSize.height() - tailHeight);
    for (int i = 1; i < 9; ++i) {
        const qreal angle = M_PI_2 * i / 8;
        vertices << QSGGeometry::Point2D(radius - radius * sin(angle), itemSize.height() - tailHeight - radius + radius * cos(angle));
    }

    // Update the geometry data
    QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), vertices.size());
    geometry->setDrawingMode(GL_TRIANGLE_FAN);
    QSGGeometry::Point2D *data = geometry->vertexDataAsPoint2D();
    for (int i = 0; i < vertices.size(); ++i) {
        data[i] = vertices[i];
    }
    node->setGeometry(geometry);
    node->setFlag(QSGNode::OwnsGeometry);

    return node;
}

Key Changes Explained

  • We inherit QQuickItem and enable ItemHasContents to signal that the component renders custom content.
  • The updatePaintNode method builds a Scene Graph node using vertex data (instead of QPainter), which Designer can render natively.
  • Property changes trigger an update() to refresh the Scene Graph node.

Solution 2: Create a QML Designer Plugin (Advanced)

If you need to keep using QQuickPaintedItem, you can build a Designer plugin to add preview support. This is more complex but useful for reusable components:

  1. Create a Qt Designer custom widget plugin project.
  2. Implement QDesignerCustomWidgetInterface to define your component’s metadata (name, icon, preview behavior).
  3. In createWidget(), return an instance of TextBalloon wrapped in a QQuickWidget for preview.
  4. Compile and install the plugin to Qt’s Designer plugin directory.

This approach requires more setup, so start with Solution 1 for a quick fix.


内容的提问来源于stack exchange,提问作者Shivendra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:24:46