Resize Tabs from QTabWidget to Content [duplicate]

折月煮酒 提交于 2021-02-17 06:46:27

问题


I'm using QTabWidget to show content with different sizes. How do I resize my tabs in a way that it matches my content?

Goal:

Tab1:

Tab2:

I tried to write a function that connects to QTabWidget.currentChanged(), I managed to ignore QSizePolicy, but the resize doesn't come into effect. I can however resize manually without problem.

import sys


from PyQt5.QtWidgets import (
    QApplication,
    QCheckBox
    QTabWidget,
    QVBoxLayout,
    QHBoxLayout,
    QWidget,
    QLabel,
    QLineEdit,
    QSizePolicy
)


class Window(QWidget):
    def curTabChanged(self,index):
        for i in range(self.tabs.count()):
            if i == index:
                self.tabs.widget(i).setSizePolicy(QSizePolicy.Preferred,QSizePolicy.Preferred)
            else:
                self.tabs.widget(i).setSizePolicy(QSizePolicy.Ignored,QSizePolicy.Ignored)
        #self.tabs.resize(self.tabs.widget(index).minimumSizeHint())
        self.tabs.widget(index).resize(100,100)
        self.tabs.widget(index).adjustSize()
        #self.resize(self.minimumSizeHint())
        self.resize(100,100)
        self.adjustSize()
    
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Define Volumes")
        self.resize(300, 100)
        # Create a top-level layout
        layout = QVBoxLayout()
        self.setLayout(layout)
        # Create the tab widget with two tabs
        self.tabs = QTabWidget()
        self.tabs.addTab(self.generalTabUI(), "Input")
        self.tabs.addTab(self.helpTabUI(), "Help")
        self.tabs.currentChanged.connect(self.curTabChanged)
        self.curTabChanged(0)
        layout.addWidget(self.tabs)
        self.setLayout(layout)

    def generalTabUI(self):

        """Create the General page UI."""
        generalTab = QWidget()
        layout = QHBoxLayout()
        self.label_text_left = QLabel("1-")
        self.label_text_right = QLabel("-100")
        self.textbox = QLineEdit()
        layout.addWidget(self.label_text_left)
        layout.addWidget(self.textbox)
        layout.addWidget(self.label_text_right)
        generalTab.setLayout(layout)
        return generalTab

    def helpTabUI(self):
        helpTab = QWidget()
        layout = QVBoxLayout()
        self.label = QLabel(self)
        self.label.setText("Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n\nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,\n\n quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \n\nDuis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \n\nExcepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")

        layout.addWidget(self.label)
        helpTab.setLayout(layout)
        return helpTab

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())

回答1:


QTabWidget, like QStackedWidget, uses QStackedLayout, which always has a minimum size hint computed using the minimum size hint of all of its widgets.

In order to prevent that, both sizeHint() and minimumSizeHint() should be reimplemented, and updateGeometry() should be called whenever the index changes.

In the following example I've unified the two functions, converted from :sizeHint() of QTabWidget, but in order to provide correct implementation, the original :minimumSizeHint() implementation should be adapted too.

class TabWidget(QTabWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.currentChanged.connect(self.updateGeometry)

    def minimumSizeHint(self):
        return self.sizeHint()

    def sizeHint(self):
        lc = QSize(0, 0)
        rc = QSize(0, 0)
        opt = QStyleOptionTabWidgetFrame()
        self.initStyleOption(opt)
        if self.cornerWidget(Qt.TopLeftCorner):
            lc = self.cornerWidget(Qt.TopLeftCorner).sizeHint()
        if self.cornerWidget(Qt.TopRightCorner):
            rc = self.cornerWidget(Qt.TopRightCorner).sizeHint()
        layout = self.findChild(QStackedLayout)
        layoutHint = layout.currentWidget().sizeHint()
        tabHint = self.tabBar().sizeHint()
        if self.tabPosition() in (self.North, self.South):
            size = QSize(
                max(layoutHint.width(), tabHint.width() + rc.width() + lc.width()), 
                layoutHint.height() + max(rc.height(), max(lc.height(), tabHint.height()))
            )
        else:
            size = QSize(
                layoutHint.width() + max(rc.width(), max(lc.width(), tabHint.width())), 
                max(layoutHint.height(), tabHint.height() + rc.height() + lc.height())
            )
        return size


class Window(QWidget):
    def __init__(self):
        # ...
        # no need to for a specific function, just directly call adjustSize()
        self.tabs.currentChanged.connect(self.adjustSize)

Two small suggestions. 1) Avoid unnecessary line spacings in your code, as it is distracting. 2) __init__ should preferably go at the beginning of the class, without any custom function before it: it's the "initialization", and it should not go after other things.




回答2:


I managed a hacky fix for my Code:

import sys

from PyQt5.QtCore import (
    QSize
    )

from PyQt5.QtWidgets import (
    QApplication,
    QCheckBox,
    QTabWidget,
    QVBoxLayout,
    QHBoxLayout,
    QWidget,
    QLabel,
    QLineEdit,
    QSizePolicy,
)

class Window(QWidget):
    
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Define Volumes")
        # Create a top-level layout
        layout = QVBoxLayout ()
        # Create the tab widget with two tabs
        self.tabs = QTabWidget()
        self.tabs.addTab(self.generalTabUI(), "Input")
        self.tabs.addTab(self.helpTabUI(), "Help")
        self.tabs.currentChanged.connect(self.curTabChanged)
        self.curTabChanged(0)
        layout.addWidget(self.tabs)
        self.setLayout(layout)
        self.rsz()

    def curTabChanged(self,index):
        for i in range(self.tabs.count()):
            self.tabs.widget(i).setSizePolicy(QSizePolicy.Ignored,QSizePolicy.Ignored)
        widget = self.tabs.currentWidget()
        widget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        const_width = self.tabs.widget(1).minimumSizeHint().width()
        widget.setFixedWidth(const_width)
        self.rsz()

    def rsz(self):
        for i in range(0,10):
            QApplication.processEvents()
        return self.resize(self.minimumSizeHint())

    def generalTabUI(self):
        """Create the General page UI."""
        generalTab = QWidget()
        layout = QHBoxLayout()
        self.label_text_left = QLabel("1-")
        self.label_text_right = QLabel("-100")
        self.textbox = QLineEdit()
        layout.addWidget(self.label_text_left)
        layout.addWidget(self.textbox)
        layout.addWidget(self.label_text_right)
        generalTab.setLayout(layout)
        return generalTab


    def helpTabUI(self):
        helpTab = QWidget()
        layout = QVBoxLayout()
        self.label = QLabel(self)
        self.label.setText("Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n\nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,\n\n quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \n\nDuis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \n\nExcepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
        layout.addWidget(self.label)
        helpTab.setLayout(layout)
        return helpTab


if __name__ == "__main__":

    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())


来源:https://stackoverflow.com/questions/66052416/resize-tabs-from-qtabwidget-to-content

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!