Issue
I have a main window and it only holds one tabwidget.I apply layout with mainwindow in order to make it self-adapt when changing mainwindow's size.The two tabs I have made by qtdesigner also apply layout.(just like make an individual window)These two sizehint were set to QSizePolicy.Preferred, QSizePolicy.Preferred
.I want tabwidget can adapt each QWidget minimum size when selecting different tabs,but I have no idea how to achieve it.
I have tried some ways such as an answer on stack overflow QTabWidget size depending on current Tab . But I found it not works for me.It seems that it only expends my window.
Here is my example:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form1(object):
def setupUi(self, Form1):
Form1.setObjectName("Form1")
Form1.resize(400, 300)
Form1.setMinimumSize(QtCore.QSize(400, 300))
self.horizontalLayout = QtWidgets.QHBoxLayout(Form1)
self.horizontalLayout.setObjectName("horizontalLayout")
self.pushButton = QtWidgets.QPushButton(Form1)
self.pushButton.setObjectName("pushButton")
self.horizontalLayout.addWidget(self.pushButton)
self.retranslateUi(Form1)
QtCore.QMetaObject.connectSlotsByName(Form1)
def retranslateUi(self, Form1):
_translate = QtCore.QCoreApplication.translate
Form1.setWindowTitle(_translate("Form1", "Form"))
self.pushButton.setText(_translate("Form1", "Test1"))
class Ui_Form2(object):
def setupUi(self, Form2):
Form2.setObjectName("Form2")
Form2.resize(261, 205)
Form2.setMinimumSize(QtCore.QSize(261, 205))
self.horizontalLayout = QtWidgets.QHBoxLayout(Form2)
self.horizontalLayout.setObjectName("horizontalLayout")
self.pushButton = QtWidgets.QPushButton(Form2)
self.pushButton.setObjectName("pushButton")
self.horizontalLayout.addWidget(self.pushButton)
self.retranslateUi(Form2)
QtCore.QMetaObject.connectSlotsByName(Form2)
def retranslateUi(self, Form2):
_translate = QtCore.QCoreApplication.translate
Form2.setWindowTitle(_translate("Form2", "Form"))
self.pushButton.setText(_translate("Form2", "Test2"))
class Ui_mainWindow(object):
def setupUi(self, mainWindow):
mainWindow.setObjectName("mainWindow")
mainWindow.setWindowModality(QtCore.Qt.ApplicationModal)
self.horizontalLayout = QtWidgets.QHBoxLayout(mainWindow)
self.horizontalLayout.setObjectName("horizontalLayout")
self.tabWidget = QtWidgets.QTabWidget(mainWindow)
self.tabWidget.setObjectName("tabWidget")
self.horizontalLayout.addWidget(self.tabWidget)
self.retranslateUi(mainWindow)
QtCore.QMetaObject.connectSlotsByName(mainWindow)
def retranslateUi(self, mainWindow):
_translate = QtCore.QCoreApplication.translate
mainWindow.setWindowTitle(_translate("mainWindow", "calc"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Form1 = QtWidgets.QWidget()
ui1 = Ui_Form1()
ui1.setupUi(Form1)
Form2 = QtWidgets.QWidget()
ui2 = Ui_Form2()
ui2.setupUi(Form2)
Form3 = QtWidgets.QWidget()
ui3 = Ui_mainWindow()
ui3.setupUi(Form3)
ui3.tabWidget.addTab(Form1, "test1")
ui3.tabWidget.addTab(Form2, "test2")
Form3.show()
sys.exit(app.exec_())
These are the two widget I created with qtdesigner.Each one has its own both default size and minimum size.window1window2 After that I just add them into tabwidget but their size are same.Tabwidget seems to adapt the biggest size of the two.I can't change the window size although in the tab that has small minimum size.tab1tab2
In my try with QTabWidget size depending on current Tab,I just followed the solution from the answer.Unfortunately, it doesn't work.
self.mainW.tabWidget.currentChanged.connect(self.updateSize)
def updateSize(self, index):
sizePolicyI = QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
sizePolicyP = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
for i in range(self.mainW.tabWidget.count()):
if not i == index:
self.mainW.tabWidget.widget(i).setSizePolicy(sizePolicyI)
self.mainW.tabWidget.widget(index).setSizePolicy(sizePolicyP)
self.mainW.tabWidget.widget(index).resize(self.mainW.tabWidget.widget(index).minimumSizeHint())
self.mainW.tabWidget.widget(index).adjustSize()
self.mainW.resize(self.mainW.minimumSizeHint())
self.mainW.adjustSize()
Solution
While updating the size policy of widgets might work, it's not always an effective solution, especially if those widgets have size policies that are not Preferred
.
The only, safe, way to achieve this is by using a QTabWidget subclass, since that allows complete control over what its virtual functions sizeHint()
and minimumSizeHint()
return.
class TabWidget(QTabWidget):
def minimumSizeHint(self):
if self.count() < 0:
return super().sizeHint()
baseSize = self.currentWidget().sizeHint().expandedTo(
self.currentWidget().minimumSize())
if not self.tabBar().isHidden():
tabHint = self.tabBar().sizeHint()
if self.tabPosition() in (self.North, self.South):
baseSize.setHeight(baseSize.height()
+ tabHint.height())
else:
baseSize.setWidth(baseSize.width()
+ tabHint.width())
opt = QStyleOptionTabWidgetFrame()
self.initStyleOption(opt)
return self.style().sizeFromContents(
QStyle.CT_TabWidget, opt, baseSize, self)
def sizeHint(self):
return self.minimumSizeHint()
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.tabWidget = TabWidget()
self.setCentralWidget(self.tabWidget)
self.setStyleSheet('''
QLabel {
border: 1px solid green;
}
''')
self.tabWidget.addTab(
QLabel(
'640x480',
minimumSize=QSize(640, 480),
alignment=Qt.AlignCenter
),
'First'
)
self.tabWidget.addTab(
QLabel(
'320x240',
minimumSize=QSize(320, 240),
alignment=Qt.AlignCenter
),
'Second'
)
self.tabWidget.currentChanged.connect(self.updateSize)
def updateSize(self):
self.tabWidget.updateGeometry()
super().updateGeometry()
self.adjustSize()
Note: this is not perfect. Due to the many "quirks" caused by Qt styles, the size will not be fully respected, but it's important to consider that this also happens with the default implementation.
I suspect it is a bug in the sizeFromContents
implementation of each style, as I get different results depending on the style used. Nonetheless, the above is quite compliant with the expected result.
Answered By - musicamante
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.