PDA

View Full Version : Should this work: Width of QLabel (with text)



Linwood
4th March 2017, 17:44
I was experimenting with a way to do UI's that had some compartmentalized validation that was active, as opposed to just preventing a user from leaving the field as the current validator does.

A side effect of this is I have a bunch of widgets, each composed of three pieces (QLabel, QLineEdit or other, QLabel), and I wanted to force that first QLabel in all of these to be the same width so the right side of them are aligned when the overall widget (the container of all three) is in a QVBoxLayout.

My approach was to iterate through them (in the containing widget), find the needed width of each, and then set all of them (max and min) to the maximum width.

It works perfectly in the sense of alignment, the widgets all function the way I want, but I am not getting anywhere near the correct size for the QLabel's width, so many of them are getting truncated.

12376

Notice how some lines are truncated on the left.

Are there better ways to do this, with grid or such -- not sure, but can we leave that question for a moment.

Is it practical to do what I want -- determine the size needed for the text?

Here is how I do it:

The prompt is declared:


QLabel* p;


It is put inside a QHBoxLayout, with the other two widgets following (valueWidget is defined elsewhere)>



hb = new QHBoxLayout(this);
hb->setAlignment(Qt::AlignBottom);

m = new QLabel(this);
m->setMinimumWidth(MUSICALPI_SETTINGS_MSG_MIN_WIDTH);
p = new QLabel(prompt,this);
p->setAlignment(Qt::AlignRight | Qt::AlignCenter);
hb->addWidget(p);
hb->addWidget(valueWidget);
hb->addWidget(m);
this->setObjectName(key);
p->setStyleSheet("font-size:" + QString::number(MUSICALPI_SETTINGS_FORM_DATA_FONT_ SIZE * 0.8) + "px;");
valueWidget->setStyleSheet("font-size:" + QString::number(MUSICALPI_SETTINGS_FORM_DATA_FONT_ SIZE) + "px; font-style: bold;");
m->setStyleSheet("font-size:" + QString::number(MUSICALPI_SETTINGS_FORM_DATA_FONT_ SIZE) + "px; color: darkRed;");
hb->setContentsMargins(0,0,0,0);


And then to return its width a public function in this containing widget is called while iterating over all of them on the screen:



int settingsItem::getPromptWidth()
{
int ret = p->fontMetrics().boundingRect(p->text()).width();
qDebug() << "Width of '" << p->text() << "' is " << ret;
return ret;
}


It is returning items that track the actual prompt length (i.e. longer prompts result in bigger numbers), but the widths are much too small.

When I use these to force the widget width, they get exactly the width I force (i.e. the problem is in the width calculation, not how I push it back to all widgets).

And if I force the calculated width to be larger (e.g. double it) it all works fine, though that's basically hard coding (of sorts) which I was trying to avoid.

Should the above work?

is the container (which holds many of these individual triple-widgets) somehow affecting the calculation?

d_stranz
4th March 2017, 18:41
It isn't clear where you are calling this function to get the width, but remember that until the widget's showEvent() occurs, the sizes of the parent widget and children within it have not yet been finalized. If you are trying to do this in the constructor it generally won't work.

So implement showEvent() for your parent widget and set the sizes there.

Linwood
4th March 2017, 22:23
Bingo.

It was called from a containing widget but before anything did a "show" on the container, so these had not been shown either. I added a this->show() to the containing widget (that holds the layout for all these individual widgets I am sizing part of), just prior to looping through to get their lengths, and it worked almost perfectly. I think it's returning the width of the text, and there's probably still a frame or margin or something, so it was just a few (like 5) pixels too short. I added a 5% slop factor (which isn't too unreasonable I think) and it works fine; I tried a variety of phrases and changes in wording, and everything lines up perfectly.

Thank you.