Home > OS >  Qt window resize height to fit QLabel text
Qt window resize height to fit QLabel text

Time:11-04

I want to create a window which height should be equal to the height of the child QLabel, the QLabel can be set to any size text and setWrap is True. Here is my current code:

class TextWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setFixedWidth(230)
        self.centralwidget = QWidget(self)
        self.centralwidget.setObjectName("centralwidget")
        self.horizontalLayout = QHBoxLayout(self.centralwidget)
        self.horizontalLayout.setSizeConstraint(QLayout.SizeConstraint.SetMinimumSize)
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout.setSpacing(0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.label = QLabel(self.centralwidget)
        self.label.setWordWrap(True)
        self.label.setObjectName("label")
        self.horizontalLayout.addWidget(self.label)
        self.setCentralWidget(self.centralwidget)
        self.label.setText("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur non urna nisl. Integer venenatis aliquet faucibus. Nam tristique massa a vestibulum congue. Vivamus nisi felis, volutpat vitae neque quis, pharetra tristique massa. Duis tincidunt et nulla a hendrerit. Vestibulum in molestie lectus.")

Actual behavior:

When big text

When a little text

The text is cut off if there is a lot of it and if there is not enough of it, then there are huge margins between the edge of the window and the text, I want the window height to wrap the text, that is, the height of the window needs to be equal to the size of the text. How can this be done?

CodePudding user response:

Get the size hint of the QLabel using the sizeHint() method and then use the result when you resize your window.

For example:

text = "Some very long text that will possible need to be wrapped and take up more than one line."

value = 3   # <--- raise or lower value to see adjustments

class Window(QMainWindow):

    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.central = QWidget()
        self.layout = QVBoxLayout(self.central)
        self.setCentralWidget(self.central)
        self.label = QLabel(text=text * value)
        self.layout.addWidget(self.label)
        self.label.setWordWrap(True)
        self.resize(self.label.sizeHint())

CodePudding user response:

This is explained in the Layout Issues section of the layout documentation:

The use of rich text in a label widget can introduce some problems to the layout of its parent widget. Problems occur due to the way rich text is handled by Qt's layout managers when the label is word wrapped".

Note that, as a rule of thumb, you shall never rely on the size hint of a label that uses word-wrapped text. This is related to the many problems text laying out has, like unexpected font behavior, system font scaling, high DPI settings. In reality, it's a good thing that the default behavior doesn't consider the possible size hint of a word-wrapped label, otherwise there could be serious performance issues, especially while resizing.

Truth is, word-wrapped text should always be displayed in a scroll area (using a QTextEdit or with a QLabel that is placed inside a QScrollArea); the default API cannot know the infinite possibilities in which some text could be shown, and should always aim for the best result with optimal performance.

The problem is caused by the fact that there's no way to know the "best" size hint of a label that can wrap its contents, and layout managers should always try to be as fast as possible in their response, otherwise you'd risk recursion or unnecessary overhead, even for a simple label.

IF you are completely sure about the fixed width of the label, you should explicitly set it:

self.label.setFixedWidth(230)
  • Related