如何使 QTabWidget 中的一个标签栏成为可消耗的?

How to make one tab bar in QTabWidget expendable?

我需要自定义我的 QTabWidget,以便其中一个选项卡栏(可以说总共有 4 个选项卡)扩展 属性 并将填充其他选项卡之间的剩余 space。有什么想法吗?

您可以继承 QTabBar,将其设置为您的 tabwidget 的宽度(高度取决于字体大小)并覆盖 tabSizeHint():

class tabBar(QTabBar):

    def __init__(self, width, height, parent=None):
        QTabBar.__init__(self, parent)
        self.setFixedSize(width, height)

    def tabSizeHint(self, i):
        f = 3                           # Tab3 shall be f times wider then the other tabs
        tw = int(self.width()/(self.count() + f -1))        # width per Tab
        if i == 2:                      # Tab3                      
            # return QSize(tw*f, self.height())         edited -> rounding error possible
            return QSize(self.width() - (self.count() - 1)*tw, self.height())
        return QSize(tw, self.height())             # all other tabs

并将此选项卡栏设置为您的选项卡小部件:

tb = tabBar(tabWidget.width(), 34)                  # tabBars height depends on fontSize
tabwidget..setTabBar(tb)

看起来像这样:

编辑:

如果调整 tabWidget 的大小,则会发生 resizeEvent()。此时 tabWidget 已经有了新的大小,并在 resizeEvent() 之后立即重新绘制, see QT-Doc QTabWidget.resizeEvent

所以如果tabBar的width()resizeEvent()中被适配,tabBar将始终与tabwidget具有相同的宽度。因为 tabSizeHint() 取决于宽度,所以所有选项卡也将具有正确的宽度。因此,您可以子类化 QTabWidget() 并覆盖 resizeEvent() 以获得动态解决方案:

class tabWidget(QTabWidget):

    def __init__(self, parent=None):
        QTabWidget.__init__(self, parent)

    def resizeEvent(self, event):
        self.tabBar().setFixedWidth(self.width())
        QTabWidget.resizeEvent(self, event)

要正确执行此操作,有必要从选项卡的现有大小倒推。这是因为选项卡大小受当前样式以及选项卡关闭按钮等其他功能的影响。为可扩展的选项卡设置最小尺寸也很重要(否则它可能会被调整为无)。

这是一个简单的演示,可以执行所有这些操作:

from PyQt4 import QtCore, QtGui

class TabBar(QtGui.QTabBar):
    def __init__(self, expanded=-1, parent=None):
        super(TabBar, self).__init__(parent)
        self._expanded = expanded

    def tabSizeHint(self, index):
        size = super(TabBar, self).tabSizeHint(index)
        if index == self._expanded:
            offset = self.width()
            for index in range(self.count()):
                offset -= super(TabBar, self).tabSizeHint(index).width()
            size.setWidth(max(size.width(), size.width() + offset))
        return size

class TabWidget(QtGui.QTabWidget):
    def __init__(self, expanded=-1, parent=None):
        super(TabWidget, self).__init__(parent)
        self.setTabBar(TabBar(expanded, self))

    def resizeEvent(self, event):
        self.tabBar().setMinimumWidth(self.width())
        super(TabWidget, self).resizeEvent(event)

class Window(QtGui.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.tabs = TabWidget(2, self)
        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.tabs)
        for text in 'One Two Three Four'.split():
            self.tabs.addTab(QtGui.QWidget(self), text)

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.setGeometry(500, 300, 400, 200)
    window.show()
    sys.exit(app.exec_())