Issue
I have created a browser but when tab reached to the last of the UI the tab not collapse like chrome but still remain in same width.
What I want?
I want when tab reached to last the tab should be collapse like chrome browser.
What I want. In the above pic the width of the tabs remain same not collapse or shrink... but in the below pic the tabs in the chrome browser shrink gradually as we add more tabs
Solution
QTabBar doesn't support that, and you need to implement it on your own.
The solution uses tabSizeHint()
, which returns a size that normally suits the contents of each tab, but in this case you need to return a default standard size and a smaller one whenever the available space is less than required.
Note that since resizing the tabs calls again both tabSizeHint()
and minimumTabSizeHint()
, you need to add a system that avoids infinite recursion.
The current QStyle and font metrics are used to compute the minimum and default sizes, and the tab widget needs to update the optimal size of the tab bar whenever it's resized.
class ShrinkTabBar(QtWidgets.QTabBar):
_widthHint = -1
_initialized = False
_recursiveCheck = False
addClicked = QtCore.pyqtSignal()
def __init__(self, parent):
super().__init__(parent)
self.setElideMode(QtCore.Qt.ElideRight)
self.setExpanding(False)
self.setTabsClosable(True)
self.addButton = QtWidgets.QToolButton(self.parent(), text='+')
self.addButton.clicked.connect(self.addClicked)
self._recursiveTimer = QtCore.QTimer(singleShot=True, timeout=self._unsetRecursiveCheck, interval=0)
self._closeIconTimer = QtCore.QTimer(singleShot=True, timeout=self._updateClosable, interval=0)
def _unsetRecursiveCheck(self):
self._recursiveCheck = False
def _updateClosable(self):
self.setTabsClosable(self._widthHint >= self._minimumCloseWidth)
def _computeHints(self):
if not self.count() or self._recursiveCheck:
return
self._recursiveCheck = True
opt = QtWidgets.QStyleOptionTab()
self.initStyleOption(opt, 0)
width = self.style().pixelMetric(QtWidgets.QStyle.PM_TabBarTabHSpace, opt, self)
iconWidth = self.iconSize().width() + 4
self._minimumWidth = width + iconWidth
# default text widths are arbitrary
fm = self.fontMetrics()
self._minimumCloseWidth = self._minimumWidth + fm.width('x' * 4) + iconWidth
self._defaultWidth = width + fm.width('x' * 17)
self._defaultHeight = super().tabSizeHint(0).height()
self._minimumHint = QtCore.QSize(self._minimumWidth, self._defaultHeight)
self._defaultHint = self._tabHint = QtCore.QSize(self._defaultWidth, self._defaultHeight)
self._initialized = True
self._recursiveTimer.start()
def _updateSize(self):
if not self.count():
return
frameWidth = self.style().pixelMetric(
QtWidgets.QStyle.PM_DefaultFrameWidth, None, self.parent())
buttonWidth = self.addButton.sizeHint().width()
self._widthHint = (self.parent().width() - frameWidth - buttonWidth) // self.count()
self._tabHint = QtCore.QSize(min(self._widthHint, self._defaultWidth), self._defaultHeight)
# dirty trick to ensure that the layout is updated
if not self._recursiveCheck:
self._recursiveCheck = True
self.setIconSize(self.iconSize())
self._recursiveTimer.start()
def minimumTabSizeHint(self, index):
if not self._initialized:
self._computeHints()
return self._minimumHint
def tabSizeHint(self, index):
if not self._initialized:
self._computeHints()
return self._tabHint
def tabLayoutChange(self):
if self.count() and not self._recursiveCheck:
self._updateSize()
self._closeIconTimer.start()
def tabRemoved(self, index):
if not self.count():
self.addButton.setGeometry(1, 2,
self.addButton.sizeHint().width(), self.height() - 4)
def changeEvent(self, event):
super().changeEvent(event)
if event.type() in (event.StyleChange, event.FontChange):
self._updateSize()
def resizeEvent(self, event):
if not self.count():
super().resizeEvent(event)
return
self._recursiveCheck = True
super().resizeEvent(event)
height = self.sizeHint().height()
if height < 0:
# a tab bar without tabs returns an invalid size
height = self.addButton.height()
self.addButton.setGeometry(self.geometry().right() + 1, 2,
self.addButton.sizeHint().width(), height - 4)
self._closeIconTimer.start()
self._recursiveTimer.start()
class ShrinkTabWidget(QtWidgets.QTabWidget):
addClicked = QtCore.pyqtSignal()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._tabBar = ShrinkTabBar(self)
self.setTabBar(self._tabBar)
self._tabBar.addClicked.connect(self.addClicked)
def resizeEvent(self, event):
self._tabBar._updateSize()
super().resizeEvent(event)
Answered By - musicamante
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.