Search code examples
pythonpython-3.xpyqtqtreeviewqsplitter

How to set the initial size of a QTreeView in a QSplitter?


I have a QTreeView inside of a QSplitter that I want to set the initial size of. I have found that I can set both setMinimumWidth(val) and setFixedWidth(val) on the QTreeView, but neither of those seem to do what I need.

The setMinimumWidth(val) only prevents the QTreeView from getting smaller than the value of val, and setFixedWidth prevents the user from resizing the QTreeView entirely.

Is there anyway to set the initial size, either by setting QSplitter or setting QTreeView? I assume I need to set the sizeHint, but I'm not quite sure.

I'm using Python 3 with PyQt5


Solution

  • You can reimplement sizeHint to set the initial size:

    class TreeView(QtWidgets.QTreeView):
        def sizeHint(self):
            size = super().sizeHint()
            size.setWidth(320)
            return size
    

    However, if creating a subclass is not desirable, and you don't mind setting a proportional initial size, you can use QSplitter.setSizes. The Qt docs define the behaviour of this method in this way:

    The overall size of the splitter widget is not affected. Instead, any additional/missing space is distributed amongst the widgets according to the relative weight of the sizes. [emphasis added]

    So it doesn't matter if sum of the sizes is larger than the splitter; all that matters is the relative weights. Given this, we can just calculate the maximum possible size available, and then divide it up accordingly, like this:

    width = QtWidgets.qApp.desktop().availableGeometry(self).width()
    self.splitter.setSizes([width * 2/3, width * 1/3])
    

    This will make the first widget twice as large as the second.

    In addition to these approaches, you can also use QSplitter.saveState and QSplitter.restoreState to save and restore the splitter sizes set by the user from a previous session.

    PS:

    If you're using Qt Designer, the above sizeHint approach can be used with widget promotion, which is quite simple to implement. See this answer for an explanation of how to do this.