Reputation: 7360
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
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