【问题标题】:Problem resizing QTabWidget according to tab content (PyQT)根据标签内容调整 QTabWidget 大小的问题 (PyQT)
【发布时间】:2021-07-26 18:30:00
【问题描述】:

我知道有一些关于 QTabWidget 调整大小的答案(Link 1Link 2 等);但是,我无法让它在我的应用程序中正常工作。

这个想法是创建一个根据 QTabWidget 大小调整大小的窗口。目前,我有两个标签,第一个比另一个小。

当我按下第二个选项卡时,窗口大小会按预期增加,但如果我返回第一个选项卡,窗口不会缩小。我尝试更改每个选项卡的 QSizePolicy 以及调整选项卡和窗口的大小,但它不会改变结果。

如何解决窗口不缩小的问题?代码如下:


import os
import os.path
import sys

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
    QSizePolicy,
    QApplication,
    QLabel,
    QMainWindow,
    QTabWidget,
    QDesktopWidget,
    QRadioButton,
    QLineEdit,
    QVBoxLayout,
    QHBoxLayout,
    QGridLayout,
    QWidget,
)

class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupMainUi()
    
    def setupMainUi(self):
        
        self.centralWidget = QWidget()
        self.setCentralWidget(self.centralWidget)
        main_window_layout = QVBoxLayout(self.centralWidget)
        self.centralWidget.setLayout(main_window_layout)

        self.tabs = QTabWidget()
        self.tabs.addTab(self.loadTab1(), "Tab1")
        self.tabs.addTab(self.loadTab2(), "Tab2")

        self.tabs.currentChanged.connect(self.updateSizes)
        self.updateSizes(0)
        
        main_window_layout.addWidget(self.tabs)

    def updateSizes(self, index):
            
        for i in range(self.tabs.count()):
            if i != index:
                self.tabs.widget(i).setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        
        self.tabs.widget(index).setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        self.tabs.widget(index).resize(self.tabs.widget(index).minimumSizeHint())
        self.tabs.widget(index).adjustSize()
        self.resize(self.minimumSize())
        self.adjustSize()
   
    def loadTab1(self):
        
        self.ticketTab = QWidget()
        self.ticketTab.setEnabled(False)

        date_layout = QGridLayout()
        self.ticket = QLabel("Number:", self)
        self.ticket_number = QLineEdit()
        self.ticket_number.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
        date_layout.addWidget(self.ticket, 0, 0)
        date_layout.addWidget(self.ticket_number, 0, 1)
        
        self.ticketTab.setLayout(date_layout)
        
        return self.ticketTab 
    
    def loadTab2(self):
        
        self.familyTab = QWidget()
        self.familyTab.setEnabled(False)
        
        family_default_layout = QVBoxLayout()
        self.family_default_checkbox = QRadioButton("Default")
        self.family_default_checkbox.setChecked(True)
        self.family_default_checkbox.setLayoutDirection(Qt.RightToLeft) 
        family_default_layout.addWidget(self.family_default_checkbox, alignment = Qt.AlignRight)
        
        family_layout = QHBoxLayout() 
        self.family_label = QLabel("Number of Families:", self)
        self.family_number = QLineEdit()
        self.family_number.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
        self.family_number.textChanged.connect(lambda:self.checkInput(self.family_number))
        family_layout.addWidget(self.family_label, alignment=Qt.AlignLeft | Qt.AlignVCenter)
        family_layout.addWidget(self.family_number, alignment=Qt.AlignLeft | Qt.AlignVCenter)
        family_default_layout.addLayout(family_layout)
        
        temp_family_layout = QHBoxLayout() 
        self.family_label_1 = QLabel("Number of Families:", self)
        self.family_number_1 = QLineEdit()
        self.family_number_1.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
        temp_family_layout.addWidget(self.family_label_1, alignment=Qt.AlignLeft | Qt.AlignVCenter)
        temp_family_layout.addWidget(self.family_number_1, alignment=Qt.AlignLeft | Qt.AlignVCenter)
        family_default_layout.addLayout(temp_family_layout)
        
        min_sub_family_layout = QHBoxLayout() 
        self.min_subfamily_label = QLabel("Minimum Number of SubFamilies:", self)
        self.min_subfamily_number = QLineEdit()
        self.min_subfamily_number.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
        min_sub_family_layout.addWidget(self.min_subfamily_label, alignment=Qt.AlignLeft | Qt.AlignVCenter)
        min_sub_family_layout.addWidget(self.min_subfamily_number, alignment=Qt.AlignLeft | Qt.AlignVCenter)
        family_default_layout.addLayout(min_sub_family_layout)
        
        max_sub_family_layout = QHBoxLayout() 
        self.max_subfamily_label = QLabel("Maximum Number of SubFamilies:", self)
        self.max_subfamily_number = QLineEdit()
        self.max_subfamily_number.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
        max_sub_family_layout.addWidget(self.max_subfamily_label, alignment=Qt.AlignLeft | Qt.AlignVCenter)
        max_sub_family_layout.addWidget(self.max_subfamily_number, alignment=Qt.AlignLeft | Qt.AlignVCenter)
        family_default_layout.addLayout(max_sub_family_layout)
        
        self.familyTab.setLayout(family_default_layout)
        
        return self.familyTab
    
os.chdir("../..")

app = QApplication(sys.argv)
win = MainWindow()

qr = win.frameGeometry()
cp = QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
win.move(qr.topLeft()) 
win.move(win.pos().x(), win.pos().y() - 180)

win.show()
sys.exit(app.exec())

抱歉这个简单的问题。直到最近我才开始探索 PyQT。

【问题讨论】:

    标签: python qt pyqt pyside


    【解决方案1】:

    QTabWidget 基于QStackedWidget,始终使用所有页面中最大的尺寸提示。

    为了避免这种情况,您可以同时覆盖 sizeHintminimumSizeHint 并确保它只返回 当前 小部件提示。

    然后,由于调整大小需要一些内部事件处理,您可以通过调用processEvents()然后调用adjustSize 来确保应用程序这样做。

    class ResizingTabWidget(QTabWidget):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.currentChanged.connect(self.updateGeometry)
    
        def minimumSizeHint(self):
            return self.sizeHint()
    
        def sizeHint(self):
            current = self.currentWidget()
            if not current:
                return super().sizeHint()
            return current.sizeHint()
    
    
    class MainWindow(QMainWindow):
        # ...
        def setupMainUi(self):
            # ...
            self.tabs = ResizingTabWidget()
            # ...
    
        def updateSizes(self):
            QApplication.processEvents()
            self.adjustSize()
    

    请注意,您无需在__init__ 中调用updateSizes
    另外,请注意,从用户体验的角度来看,这不是一个很好的方法,因为不断调整自身大小的 UI 被许多人认为是烦人的,并且经常使用户感到困惑。

    【讨论】:

    • 欣赏答案!我尝试添加解决方案,但问题仍然存在。窗口在 tab1 -> tab2 时调整大小,但在 tab1 恢复时不会发生同样的情况。我在您的回答中注意到您没有更改 QSizePolicy。这不是必要的吗?谢谢
    • @LeonardoFerreira 您不会尝试将代码添加到updateSizes,对吧?它应该只有上面指定的两行。此外,不应为此更改尺寸政策。
    • @musicamante updateSizes 叫什么名字?
    • @UmbralReaper 当tab QTabWidget 发送其currentChanged 信号时,请参阅原始代码。
    • @musicamante 这是有道理的。我承认我倾向于对大块代码感到困惑。
    猜你喜欢
    • 1970-01-01
    • 2018-10-10
    • 2014-04-29
    • 2011-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-09
    相关资源
    最近更新 更多