Skip to content

Instantly share code, notes, and snippets.

@michalfapso
Last active May 7, 2020 20:13
Show Gist options
  • Save michalfapso/f1ecac7e81dc986cb3bc941abe85d5e4 to your computer and use it in GitHub Desktop.
Save michalfapso/f1ecac7e81dc986cb3bc941abe85d5e4 to your computer and use it in GitHub Desktop.
How to automatically increase/decrease text size in label in Qt - comment on https://stackoverflow.com/a/42690033/1341914
// standard C++ header:
#include <iostream>
#include <string>
// Qt header:
#include <QApplication>
#include <QBoxLayout>
#include <QFrame>
#include <QGroupBox>
#include <QLabel>
#include <QLineEdit>
#include <QMainWindow>
#include <QStyle>
#include <QDebug>
#define DBG(msg) qDebug() << __FILE__ << ":" << __LINE__ << "> " << msg;
//#define CHECK_ONLY_HEIGHT
using namespace std;
class Label: public QLabel {
public:
void layout();
QRect documentRect(); // borrowed from QLabelPrivate
protected:
virtual void resizeEvent(QResizeEvent *pQEvent);
};
QRect Label::documentRect()
{
QRect rect = contentsRect();
int m = margin(); rect.adjust(m, m, -m, -m);
layoutDirection();
const int align
= QStyle::visualAlignment(layoutDirection(), QLabel::alignment());
int i = indent();
if (i < 0 && frameWidth()) { // no indent, but we do have a frame
m = fontMetrics().width(QLatin1Char('x')) / 2 - m;
}
if (m > 0) {
if (align & Qt::AlignLeft) rect.setLeft(rect.left() + m);
if (align & Qt::AlignRight) rect.setRight(rect.right() - m);
if (align & Qt::AlignTop) rect.setTop(rect.top() + m);
if (align & Qt::AlignBottom) rect.setBottom(rect.bottom() - m);
}
return rect;
}
void Label::layout()
{
// get initial settings
QString text = this->text();
if (text.isEmpty()) return;
QRect rectLbl = documentRect(); // wrong: contentsRect();
QFont font = this->font();
int size = font.pointSize();
QFontMetrics fontMetrics(font);
QRect rect = fontMetrics.boundingRect(rectLbl,
Qt::TextWordWrap, text);
// decide whether to increase or decrease
int step = rect.height() > rectLbl.height() ? -1 : 1;
// iterate until text fits best into rectangle of label
for (;;) {
font.setPointSize(size + step);
QFontMetrics fontMetrics(font);
rect = fontMetrics.boundingRect(rectLbl,
Qt::TextWordWrap, text);
if (size <= 1) {
cout << "Font cannot be made smaller!" << endl;
break;
}
if (step < 0) {
size += step;
#ifdef CHECK_ONLY_HEIGHT
if (rect.height() < rectLbl.height()) break;
#else
if (rect.height() < rectLbl.height() ||
rect.width () < rectLbl.width ()) break;
#endif
} else {
#ifdef CHECK_ONLY_HEIGHT
if (rect.height() > rectLbl.height()) break;
#else
if (rect.height() > rectLbl.height() ||
rect.width () > rectLbl.width ()) break;
#endif
size += step;
}
DBG("size:"<<size<<" step:"<<step<<" rect:"<<rect<<" rectLbl:"<<rectLbl<<" contentsRect:"<<contentsRect());
}
DBG("size:"<<size<<" rect:"<<rect<<" rectLbl:"<<rectLbl<<" contentsRect:"<<contentsRect());
// apply result of iteration
font.setPointSize(size);
setFont(font);
}
void Label::resizeEvent(QResizeEvent *pQEvent)
{
QLabel::resizeEvent(pQEvent);
layout();
}
int main(int argc, char **argv)
{
cout << QT_VERSION_STR << endl;
// main application
#undef qApp // undef macro qApp out of the way
QApplication qApp(argc, argv);
// setup GUI
QMainWindow qWin;
QGroupBox qGBox;
QVBoxLayout qBox;
Label qLbl;
qLbl.setText("aaa abcdefghijklmno bbbb ccccc");
qLbl.setMinimumSize(QSize(200, 200));
qLbl.setMaximumSize(QSize(200, 200));
qLbl.setFrameStyle(Label::Box);
qLbl.setFrameShadow(Label::Sunken);
qLbl.setWordWrap(true);
qBox.addWidget(&qLbl, 1);
QLineEdit qTxt;
qTxt.setText(qLbl.text());
qBox.addWidget(&qTxt, 0);
qGBox.setLayout(&qBox);
qWin.setCentralWidget(&qGBox);
qWin.show();
// install signal handlers
QObject::connect(&qTxt, &QLineEdit::editingFinished,
[&qTxt, &qLbl]() {
QString text = qTxt.text();
qLbl.setText(text);
qLbl.layout();
});
return qApp.exec();
}
@pbrais
Copy link

pbrais commented May 7, 2020

On line 79, I replaced the || with an &&. The algorithm works better when the initial font is big and stepping towards a smaller value. But there is still a missing step.

Tried with T, then The quick brown fox jumps over the lazy dog, then a last enter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment