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


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.

Best 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.

Related Question