PyQt: how to handle auto-resize of widgets when their content changes

c++, pyqt4, python, qt, qt4

Solution

I'm answering in C++ here, since that's what I'm most familiar with, and your problem isn't specific to PyQt.

Normally, you just need to call `QWidget::updateGeometry()` when the `sizeHint()` may have changed, just like you need to call `QWidget::update()` when the contents may have changed.

Your problem, however, is that the `sizeHint()` doesn't change when text is added to `QLineEdit` and `QTextEdit`. For a reason: People don't expect their dialogs to grow-as-they-type :)

That said, if you really want grow-as-you-type behaviour in those widgets you need to inherit from them and reimplement `sizeHint()` and `minimumSizeHint()` to return the larger size, and potentially `setText()`, `append()` etc. to call `updateGeometry()` so the sizehint change is noticed.

The sizehint calculation won't be entirely trivial, and will be way easier for `QLineEdit` than for `QTextEdit` (which is secretly a `QAbstractScrollArea`), but you can look at the `sizeHint()` and `minimumSizeHint()` implementations for inspiration (also the one for `QComboBox`, which has a mode to do exactly what you want: `QComboBox::AdjustToContents`.

EDIT: Your two usecases (QTextBrowser w/o scrollbars and QLineEdit instead of QLabel just for selecting the text in there) can be solved by using a QLabel and a recent enough Qt. QLabel has gained both link-clicking notification and so-called "text-interaction flags" (one of which is TextSelectableByMouse) in Qt 4.2. The only difference that I was able to make out is that loading new content isn't automatic, there's no history, and there's no micro focus hinting (ie. tabbing from link to link) in QLabel.

Problem

I am having some issues with the size of qt4 widgets when their content changes. I will illustrate my problems with two simple scenarios: Scenario 1: I have a QLineEdit widget. Sometimes, when I'm changing its content using QLineEdit.setText(), the one-line string doesn't fit into the widget at its current size anymore. I must select the widget and use the arrow keys to scroll the string in both directions in order to see it all. Scenario 2: I have a QTextEdit widget. Sometimes, when I'm changing its content using QTextEdit.setHtml(), the rendered HTML content doesn't fit into the widget at its current size anymore. The widget starts displaying horizontal and/or vertical scroll bars and I can use them to scroll the HTML content. What I would want in such scenarios is to have some logic that decides if after a content change, the new content won't fit anymore into the widget and automatically increase the widget size so everything would fit. How are these scenarios handled? I'm using PyQt4. Edit: after reading both the comment and the first answer (which mentions typing content into the widget), I went over the question one more time. I was unpleasantly surprised to find out a horrible typo. I meant QTextBrowser when I wrote QTextEdit, my apologies for misleading you. That is: I have a widget which renders HTML code that I'm changing and I would want the widget to grow enough to display everything without having scrollbars. As for QLineEdit instead of QLabel - I went for QLineEdit since I've noticed I can't select text from a QLabel with the mouse for copying it. With QLineEdit it is possible.

Original source