PyQT5 QTabbar 展开选项卡 header

PyQT5 QTabbar Expand tab header

我正在编写一个只有两个选项卡的 QTabwidget。但是选项卡 headers (名称)不适合 QTabwidget 宽度。我想适应标签栏的长度(两个标签headers)

import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton, QWidget, QAction, QTabWidget,QVBoxLayout
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot

class App(QMainWindow):

    def __init__(self):
        super().__init__()

        self.table_widget = MyTableWidget(self)
        self.setCentralWidget(self.table_widget)
        
        self.show()
    
class MyTableWidget(QWidget):
    
    def __init__(self, parent):
        super(QWidget, self).__init__(parent)
        self.layout = QVBoxLayout(self)
        
        self.tabs = QTabWidget()
        """ Here I want to fit the two tab 
            headers withthe QTabwidget width
        """
        self.tab1 = QWidget()
        self.tab2 = QWidget()
        self.tabs.resize(300,200)
        
        self.tabs.addTab(self.tab1,"Tab 1")
        self.tabs.addTab(self.tab2,"Tab 2")
        
        # Create first tab
        self.tab1.layout = QVBoxLayout(self)
        
        self.layout.addWidget(self.tabs)
        self.setLayout(self.layout)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())

受此answer的启发,我认为您可以重写showEvent(甚至resizeEvent)来计算新的宽度并通过样式表进行设置。

它不是规范的,但它确实起作用了。

import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QTabWidget, QVBoxLayout


class App(QMainWindow):

    def __init__(self):
        super().__init__()
        self.table_widget = MyTableWidget(self)
        self.setCentralWidget(self.table_widget)

        self.show()


class MyTableWidget(QWidget):
    def __init__(self, parent):
        super(QWidget, self).__init__(parent)
        self.layout = QVBoxLayout(self)

        self.tabs = QTabWidget()
        self.tabs.tabBar().setExpanding(True)
        self.tab1 = QWidget()
        self.tab2 = QWidget()
        self.tabs.resize(300, 200)

        self.tabs.addTab(self.tab1, "Tab 1")
        self.tabs.addTab(self.tab2, "Tab 2")

        # Create first tab
        self.tab1.layout = QVBoxLayout(self)

        self.layout.addWidget(self.tabs)
        self.setLayout(self.layout)

    def resizeEvent(self, event):
        super().resizeEvent(event)
        self._set_tabs_width()

    def showEvent(self, event):
        super().showEvent(event)
        self._set_tabs_width()

    def _set_tabs_width(self):
        tabs_count = self.tabs.count()
        tabs_width = self.tabs.width()
        tab_width = tabs_width / tabs_count
        css = "QTabBar::tab {width: %spx;}" % tab_width
        self.tabs.setStyleSheet(css)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())

标签的大小是使用当前 QStyle 给出的提示计算的。

由于QTabWidget使用tabbar的sizeHint来设置tabbar的大小,而sizeHint通常是基于tabSizeHint(),你必须重新实现:

  • 需要 sizeHint() 才能提供与父级相同的宽度(或高度);
  • tabSizeHint() 考虑了 sizeHint() 的基本实现,以根据选项卡的内容计算提示,如果它小于当前大小,它会建议一个基于可用大小的大小 space 除以标签数;
class TabBar(QtWidgets.QTabBar):
    def sizeHint(self):
        hint = super().sizeHint()
        if self.isVisible() and self.parent():
            if not self.shape() & self.RoundedEast:
                # horizontal
                hint.setWidth(self.parent().width())
            else:
                # vertical
                hint.setHeight(self.parent().height())
        return hint

    def tabSizeHint(self, index):
        hint = super().tabSizeHint(index)
        if not self.shape() & self.RoundedEast:
            averageSize = self.width() / self.count()
            if super().sizeHint().width() < self.width() and hint.width() < averageSize:
                hint.setWidth(averageSize)
        else:
            averageSize = self.height() / self.count()
            if super().sizeHint().height() < self.height() and hint.height() < averageSize:
                hint.setHeight(averageSize)
        return hint

# ...
        self.tabWidget = QtWidgets.QTabWidget()
        self.tabWidget.setTabBar(TabBar(self.tabWidget))

请注意,这是一个非常基本的实现,在某些情况下您可能会看到标签名称很长的滚动按钮,即使理论上应该足够了space 去看看他们。