Как сделать одну панель вкладок в QTabWidget расходуемой?

Мне нужно настроить QTabWidget так, чтобы одна из его панелей вкладок (скажем, всего 4 вкладки) имела расширяющееся свойство и заполняла оставшееся пространство между другими вкладками. Любые идеи?


person Devligue    schedule 22.02.2016    source источник
comment
Вы хотите, чтобы вкладки выглядели так? /----\/-------------------\/----\   -  person Brendan Abel    schedule 22.02.2016
comment
|/''''''''TAB1'''''''\/'''''''TAB2'''''''\/''''''''''''''' '''''''''TAB3'''''''''''''''''''''''''\/''''''''TAB4''''''' \| Примерно так ;) И ширина этой 3-й вкладки неизвестна, она должна расширяться до упора и сдвигать эту последнюю вкладку вправо.   -  person Devligue    schedule 23.02.2016


Ответы (2)


вы можете создать подкласс QTabBar, установить его на ширину вашего виджета вкладки (высота зависит от размера шрифта) и перезаписать 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

и установите этот tabBar на свой виджет вкладок:

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

выглядит так:

tabwidget с расширенной вкладкой

изменить:

если изменяется размер tabWidget, возникает resizeEvent(). В этот момент tabWidget уже имеет новый размер и перерисовывается сразу после resizeEvent(), см. QT-Doc QTabWidget.resizeEvent

Таким образом, если width() панели вкладок адаптирована в resizeEvent(), панель вкладок всегда будет иметь ту же ширину, что и виджет вкладок. Поскольку 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)
person a_manthey_67    schedule 22.02.2016
comment
Что ж, это вроде сработало, но это не динамическое решение. Я имею в виду, что все разбивается, когда я начинаю изменять размер главного окна; / Все еще ценю ваше решение! - person Devligue; 23.02.2016

Чтобы сделать это правильно, необходимо работать в обратном направлении от существующих размеров вкладок. Это связано с тем, что размеры вкладок зависят от текущего стиля и других функций, таких как кнопки закрытия вкладок. Также важно установить минимальный размер вкладки, которая может быть увеличена (в противном случае ее размер может измениться до нуля).

Вот простая демонстрация, которая делает все это:

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_())
person ekhumoro    schedule 23.02.2016