Nulik
Nulik

Reputation: 7360

QQuickPaintedItem is not aligned properly

I have created a custom QQuickPaintedItem in C++, but when using it the QML side inside a ColumnLayout it ignores Q.AlignHCenter attribute. The only way to align it is to put my custom Item into an Item element. For example:

This DOESN'T work, the item is placed more on the right than true centered:

BalanceItem {
    Layout.alignment: Qt.AlignHCenter
    id: acct_balance_item
}

This DOES work, the item is trully centered:

Item {
    Layout.preferredWidth: acct_balance_item.width
    Layout.preferredHeight: acct_balance_item.height
    Layout.alignment: Qt.AlignHCenter
    BalanceItem {
        id: acct_balance_item
    }
}

My paint method goes like this:

void BalanceItem::paint(QPainter* painter) {
    int w;
    int accum_w=0;
    QColor hi_color;

    hi_color.setRgb((unsigned int) 0x00ffffff);
    QColor dot_color((QRgb) 0x00FFFFFF);
    QColor lo_color((QRgb) 0x00888888);

    QPen pen(hi_color, 2);
    painter->setPen(pen);
    QFont font=painter->font();
    font.setPointSize ( 12 );
    font.setWeight(QFont::Bold);
    QFontMetrics fm(font);
    w=fm.width(this->hi_fmt);
    painter->setFont(font);
    painter->drawText(QPoint(0,20),this->hi_fmt);
    accum_w+=w;

    w=fm.width(".");
    pen.setColor(dot_color);
    painter->setPen(pen);
    painter->drawText(QPoint(accum_w,20),".");
    accum_w+=w;


    font.setWeight(QFont::Normal);
    fm=QFontMetrics(font);
    w=fm.width(this->lo_fmt);
    painter->setFont(font);
    pen.setColor(lo_color);
    painter->setPen(pen);
    painter->drawText(QPoint(accum_w,20),this->lo_fmt);
    accum_w+=w;

    QString symstr(" "+this->symbol);
    w=fm.width(symstr);
    painter->drawText(QPoint(accum_w,20),symstr);
    accum_w+=w;

    this->fld_width=accum_w;
    this->setWidth(this->fld_width);
}

What I suspect is that it uses initial width of the item set by the Constructor , but this width is only initial setting, the real width is recalculated during paint() method, at the end.

So, how do I make my custom QQuickPaintedItem properly aligned in a ColumnLayout?

Upvotes: 0

Views: 331

Answers (1)

GrecKo
GrecKo

Reputation: 7150

Your first code doesn't work because the ColumnLayout modifies the width and height of your BalanceItem. That's what layouts do in Qt Quick, they manage the sizing and positioning of their children. In order to do that, they need to know what size their children are.

And they can't do that with width and height, cause they'll modify it later on. In your second example, had you done width: acct_balance_item.width, it would have failed too. The width and height of the Item would have ultimately been 0.

To tell a layout what size an item wants to be, they are 2 solutions. The one you used with the Layout attached properties preferred|minimum|maximum/Width|Height or the one with the implicitWidth/implicitHeight properties of Item/QQuickItem.

The implicit sizes is the size an item takes when no explicit sizes is set to it (with width and height). Some items have implicit sizes set to 0 (like a plain Item or Rectangle), but some may define their implicit size to inform a parent/user of the size it makes sense to default to. For example a Text define its implicit size so that it can fit all its text. But you can force on it a specific width, and the Text may then wrap or elide its text if the explicit width is smaller than its implicitWidth.

So your problem was that your BalanceItem has a width and height of 0 in your ColumnLayout, but you did not notice that because clippling is not enabled by default, and you painted outside your item's dimensions in your paint method.

When defining an item component, you should not set its width or height properties. If it makes sense for your item, you can define an implicitWidth or implicitHeight.

You could also handle explicit sizes by only painting in the item's area, if you can somehow squish/expand your component. But you don't have to if you can't/don't want to (Text doesn't do it if you don't enable eliding or wrapping).

To mitigate your future item geometry problems you could try debugging it by putting a child Rectangle with some color and anchors.fill: parent, maybe some opacity, to visualize the size taken by your item. Or use the excellent Qt debugging software GammaRay.

Upvotes: 2

Related Questions