问题
I'm using QTabWidget to show content with different sizes. How do I resize my tabs in a way that it matches my content?
Goal:
Tab1:
Tab2:
I tried to write a function that connects to QTabWidget.currentChanged(), I managed to ignore QSizePolicy, but the resize doesn't come into effect. I can however resize manually without problem.
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, like QStackedWidget, uses QStackedLayout, which always has a minimum size hint computed using the minimum size hint of all of its widgets.
In order to prevent that, both sizeHint()
and minimumSizeHint()
should be reimplemented, and updateGeometry()
should be called whenever the index changes.
In the following example I've unified the two functions, converted from :sizeHint()
of QTabWidget, but in order to provide correct implementation, the original :minimumSizeHint()
implementation should be adapted too.
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)
Two small suggestions. 1) Avoid unnecessary line spacings in your code, as it is distracting. 2) __init__
should preferably go at the beginning of the class, without any custom function before it: it's the "initialization", and it should not go after other things.
回答2:
I managed a hacky fix for my Code:
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_())
来源:https://stackoverflow.com/questions/66052416/resize-tabs-from-qtabwidget-to-content