将选项卡从 QTabWidget 调整为内容 [重复]

Posted

技术标签:

【中文标题】将选项卡从 QTabWidget 调整为内容 [重复]【英文标题】:Resize Tabs from QTabWidget to Content [duplicate] 【发布时间】:2021-02-04 19:20:26 【问题描述】:

我正在使用 QTabWidget 来显示不同大小的内容。如何调整标签的大小以使其与我的内容相匹配?

目标:

表 1:

Tab2:

我尝试编写一个连接到 QTabWidget.currentChanged() 的函数,我设法忽略了 QSizePolicy,但调整大小没有生效。但是,我可以毫无问题地手动调整大小。

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 和 QStackedWidget 一样,使用QStackedLayout,它总是有一个使用其所有小部件的最小尺寸提示计算的最小尺寸提示。

为了防止这种情况发生,sizeHint()minimumSizeHint() 都应该重新实现,并且每当索引更改时都应该调用 updateGeometry()

在下面的例子中我统一了这两个函数,从QTabWidget的:sizeHint()转换而来,但是为了提供正确的实现,原来的:minimumSizeHint()的实现也要适应。

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)

两个小建议。 1) 避免代码中不必要的行距,因为它会分散注意力。 2) __init__ 最好放在类的开头,前面没有任何自定义函数:它是“初始化”,它不应该放在其他东西之后。

【讨论】:

非常感谢,我对这些东西真的很陌生。我找到了一个让我的标签垂直调整大小的 hacky 修复,你能看一下吗?我使用了这篇文章中的一个技巧***.com/questions/28660960/…。 这篇文章已关闭:我在这里发布了一个新问题:***.com/questions/66054857/… 我强烈建议您仔细研究我的代码以及有关使用的所有类和函数的文档。这不是即时的东西,你不能指望在几分钟内修复。此外,QLabel 在布局方面存在一些问题,因为它可以包含富文本并具有合适的大小(请参阅Layout issues)。【参考方案2】:

我为我的代码管理了一个 hacky 修复:

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_())

【讨论】:

以上是关于将选项卡从 QTabWidget 调整为内容 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

当添加子选项卡时,如何使 qtabwidget 实例自动调整大小?

在运行时使用 QTabWidget 将内容加载到选项卡中

createBottomTabNavigator 无法将选项卡从路线 3 更改为路线 2

PyQt:可编辑的 QTabWidget 选项卡文本

如何将 QTabWidget 中的一个选项卡设置为在 Qt 中不可移动?

QTabWidget 访问实际选项卡(不是内容小部件)