Search code examples
qtqt-designerqtextedit

Can I have single line sized QTextEdit with simple html?


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?


Solution

  • 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();
    }