5

I need to display simple status row with text which will contain following styles:

  • color
  • bold
  • italic

QTextEdit can render simple HTML. But it also forcibly expands over multiple lines:

image description

Red background was added to emphasize the dimensions of the QTextEdit. Desired size is the size of one text line. How do I achieve that?

IAmInPLS
  • 4,051
  • 4
  • 24
  • 57
Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778

5 Answers5

6

First of all, if you've simply used a QLabel, you'd not need to do anything special: it supports rich text format, and only takes as much space as necessary:

#include <QtWidgets>
int main(int argc, char ** argv) {
   QApplication app{argc, argv};
   QWidget w;
   QVBoxLayout layout{&w};
   QLineEdit edit;
   QLabel message{"Foo <font color=\"red\">Bar!</font>"};
   message.setTextFormat(Qt::RichText);
   message.setWordWrap(true);
   message.setFrameStyle(QFrame::Box);
   layout.addWidget(&edit);
   layout.addWidget(&message);
   layout.addStretch();
   QObject::connect(&edit, &QLineEdit::textChanged, &message, &QLabel::setText);
   w.show();
   return app.exec();
}

If you insist to use a QTextEdit: It contains a QTextDocument, laid out by its documentLayout(). The layout emits a signal each time its size changes. You can act on that signal to change the height of the widget to accommodate the size of the document. Take into account the structure of a QTextEdit: it is a QAbstractScrollArea and the contents are shown in the viewport() widget. The goal is for the viewport() to be large enough to fit the text document. The widget itself may be bigger, depending on the active style or style sheet.

Below is an example of how you might implement this. The contents of the line edit are propagated to the read-only message QTextEdit, so that you can note how the widget size is updated in the real time as the text gets too long to fit in one line. This automatically takes care of updating the size when you change the width of the widget, as the document size changes as well due to height-for-width trade-off.

// https://github.com/KubaO/stackoverflown/tree/master/questions/textedit-height-37945130
#include <QtWidgets>

void updateSize(QTextEdit * edit) {
   auto textHeight = edit->document()->documentLayout()->documentSize().height();
   edit->setFixedHeight(textHeight + edit->height() - edit->viewport()->height());
}

int main(int argc, char ** argv) {
   QApplication app{argc, argv};
   QWidget w;
   QVBoxLayout layout{&w};
   QLineEdit edit;
   QTextEdit message;
   message.setReadOnly(true);
   message.setText("Foo Bar!");
   layout.addWidget(&edit);
   layout.addWidget(&message);
   layout.addStretch();
   QObject::connect(&edit, &QLineEdit::textChanged, &message, &QTextEdit::setPlainText);
   QObject::connect(message.document()->documentLayout(),
                    &QAbstractTextDocumentLayout::documentSizeChanged,
                    &message, [&]{ updateSize(&message); });
   w.show();
   return app.exec();
}
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
3

Maybe simple solution is to use setFixedHeight method of QWidget class (Qt documentation: http://doc.qt.io/qt-5/qwidget.html#setFixedHeight)

yourTextEdit->setFixedHeight(/*Height for one text line*/);
Kirill Chernikov
  • 1,387
  • 8
  • 21
  • But how do I know pixel height of one line? – Tomáš Zato Jun 21 '16 at 13:39
  • 1
    Of course, you can use QFontMetrics. @IAmInPLS is right. It is the best way, i think. The other way - determine needed height practically, when you start you application. But this may be useful if you have only one QFont and styles for you QTextEdit. One more way - maybe use QLabel. – Kirill Chernikov Jun 21 '16 at 13:53
  • @IAmInPLS `QLabel` renders HTML? Ah, well I didn'[t know that. The sole reason for using `QTextEdit` instead of `QLabel` was to get HTML rendered... – Tomáš Zato Jun 22 '16 at 07:27
  • @TomášZato I may be wrong since I heard in many places that `QLabel` was not a good fit for rendering HTML but a code like `QLabel *labelHTML = new QLabel("Hello " "World!");` works for me so I don't know what to believe anymore – IAmInPLS Jun 22 '16 at 07:35
  • I just tried to use QLabel and it worked quite well. I guess it's not good for big HTML documents, but I just need one line of text. – Tomáš Zato Jun 22 '16 at 09:45
2

If you want the size of a text line, use QFontMetrics:

QTextEdit* textEdit = new QTextEdit();
QFontMetrics metrics(textEdit->font());
int lineHeight = metrics.lineSpacing();
textEdit->setFixedHeight(lineHeight);

You may add one or two pixels to lineHeight if it is not enough.

IAmInPLS
  • 4,051
  • 4
  • 24
  • 57
  • Guessing at widget size by saying "you may add one or two pixels" is just wrong :( – Kuba hasn't forgotten Monica Jun 21 '16 at 16:44
  • This code is enough, it is just if the final visual rendering is not convenient for the OP – IAmInPLS Jun 21 '16 at 18:08
  • You're assuming a whole lot here. It's not enough. A `QTextEdit` renders a `QTextDocument`, using a certain layout. The `QTextEdit::font` doesn't have anything to do with the font or fonts used to display the text. And so on. You're trying to reinvent the wheel, wrongly. You can't assume that a rich text layout will render in a height given by the underlying widget's font. – Kuba hasn't forgotten Monica Jun 21 '16 at 18:32
  • 1
    I'm not trying to reinvent anything, just trying to do something in a simple way... I understand now it's not the right way (which is the way you showed in your answer), but I needed it for a basic example and this is what was working for me. – IAmInPLS Jun 22 '16 at 06:50
  • 1
    If anyone else comes here looking for the size of QTextEdit to be of single line, don't do this please. Instead just create a temporary `QLineEdit` with your font and use its `sizeHint()` method to get the correct height. – Waqar Feb 16 '21 at 18:10
2

You can create and initialize your textbox like so:

QTextEdit* te = new QTextEdit ("0");
te->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
te->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
te->setLineWrapMode(QTextEdit::NoWrap);
te->setFixedHeight(50);

The critical property is setLineWrapMode, which I have set to NoWrap.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
OBA
  • 21
  • 1
0

You can use QLineEdit. I'm not sure maybe it is recently added.

bad_coder
  • 11,289
  • 20
  • 44
  • 72
Hasan Yilmaz
  • 108
  • 8