Automatically Scale Text in QLabels
-
If I have a set of QLabels in a widget, as I resize the widget I would like the QLabels not only to fill the space available (as any layout will handle), I also want the Label text to scale proportionately.
How do you go about doing this?
-
Hi,
I would reimplement resizeEvent and update the font size based on the new widget size
Hope it helps
-
to add up to SGaist:
in the resizeEvent use QLabel::contentsRect() and QFontMetrics::boundingRect() -
[quote author="raven-worx" date="1388647547"]to add up to SGaist:
in the resizeEvent use QLabel::contentsRect() and QFontMetrics::boundingRect()[/quote]Thanks...could you possibly expand a bit on what you mean by this?
-
something like this:
void MyLabel::resizeEvent(QResizeEvent* event) { QLabel::resizeEvent(event); QFont font = this->font(); QRect cRect = this->contentsRect(); if( this->text().isEmpty() ) return; int fontSize = 1; while( true ) { QFont f(font); f.setPixelSize( fontSize ); QRect r = QFontMetrics(f).boundingRect( this->text() ); if (r.height() <= cRect.height() && r.width() <= cRect.widht() ) fontSize++; else break; } font.setPixelSize(fontSize); this->setFont(font); }
Not tested though, but it should give you an idea.
-
Thanks, I will give it a try.
-
@raven-worx This method is too slow...
-
@zed962 Yea I doubt he meant it for production level code without optimizations. It was meant to give the guy an idea on how to deal with it.
If you wanted to use it in production you would need to limit the calling of the
while
loop during the resize event. I would call that only after the person had chosen a size, or maybe less often during the resizing. Or finally, use a member or static var and track sizes and only recalculate sizing as things don't fit.Don't forget most of us that answer questions on these forums pull the code right out of our heads as an example for people to base their fixes off. The code is rarely ready to be dropped into a project. But we all assume the developers asking the questions can figure out things like compiler errors (again code type from our heads) and optimizations themselves. :)
-
@ambershark sure thing and I appreciate the time everyone is taking to come up with solutions. Thanks for your solution ^^.
-
you should use something like:
#include <QLabel> #include <QTimer> class ScaleTextlabel : public QLabel{ Q_OBJECT Q_DISABLE_COPY(ScaleTextlabel) public: explicit ScaleTextlabel(QWidget* parent=Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) :QLabel(parent,f) { initTimer(); } explicit ScaleTextlabel(const QString &text, QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) :QLabel(text,parent,f) { initTimer(); } protected: void resizeEvent(QResizeEvent* event) override{ QLabel::resizeEvent(event); m_resizeTimer->start(); } protected slots: void resizeFont(){ QFont basefont = font(); const QRect baseRect = contentsRect(); const QString baseText = text(); int fontSizeGuess = qMax(1,basefont.pixelSize()); for(;;++fontSizeGuess){ QFont testFont(basefont); testFont.setPixelSize(fontSizeGuess); const QRect fontRect=QFontMetrics(testFont).boundingRect(baseText); if(fontRect.height()>baseRect.height() || fontRect.width()>baseRect.width()) break; } for(;fontSizeGuess>1;--fontSizeGuess){ QFont testFont(basefont); testFont.setPixelSize(fontSizeGuess); const QRect fontRect=QFontMetrics(testFont).boundingRect(baseText); if(fontRect.height()<=baseRect.height() && fontRect.width()<=baseRect.width()) break; } basefont.setPixelSize(fontSizeGuess); setFont(basefont); } private: void initTimer(){ m_resizeTimer=new QTimer(this); m_resizeTimer->setInterval(100); m_resizeTimer->setSingleShot(true); connect(m_resizeTimer,&QTimer::timeout,this,&ScaleTextlabel::resizeFont); } QTimer* m_resizeTimer; };