PyQt6中QGridLayout行为控制:取消勾选后恢复窗口初始布局
解决PyQt6中QGridLayout动态添加组件后窗口无法恢复初始形状的问题
核心问题分析
你遇到的问题根源在于:QGridLayout在新增列并添加组件后,即使删除组件,布局仍会保留该列的尺寸策略,导致窗口无法自动收缩回初始宽度。使用deleteLater()会直接销毁组件,不仅无法重复使用,也无法解决布局残留的列空间问题。
解决方案
方法:动态添加/移除组件+窗口自动调整
不要销毁stack1,而是通过removeWidget()将其从布局中移除并隐藏,同时调用adjustSize()让窗口根据当前布局内容自动调整大小。这种方式既可以重复使用stack1,又能让布局彻底释放多余空间。
修改后的关键代码
def cb_onclicked(self): if self.bridgingCheckBox.isChecked(): print('Puenteando') self.rejillaLayout.addWidget(self.stack1, 0, 2) self.stack1.show() self.adjustSize() # 让窗口适配新增内容 else: print('No puenteando') self.rejillaLayout.removeWidget(self.stack1) self.stack1.hide() self.adjustSize() # 恢复窗口到初始大小
完整优化代码
import sys from PyQt6.QtCore import * from PyQt6.QtGui import * from PyQt6.QtWidgets import * class Window(QDialog): def __init__(self): super().__init__() self.setWindowTitle("Anticoagulant Dose calculator") self.buttons = { 'metrics': ['Age?', 'Height in cm?', 'Serum Creatinine?', 'Weight in kg?', 'Sex?'], 'anticoagulant': ['DOAC', 'warfarin, \nacenocumarol'], 'indication': ['VTE', 'Atrial Fibrilation', 'Mechanical Heart valve'], 'VTE': ['single VTE > 12 months', 'VTE 3-12 months or \n multiple, large volume PE or \n active cancer', 'VTE < 3 months \n or known antithrombin deficiency or \n antiphospholipid syndrome'], 'af': ['No',"Yes, within the past 12 months","Yes, within the past 3 months"], 'Mech': 'mech', 'sexo': ['Male', 'Female'] } self.dialogLayout = QVBoxLayout() self.rejillaLayout = QGridLayout() self.anticoagButtongroup = QButtonGroup() self.indicationButtongroup = QButtonGroup() self.UIcomponents() self.setLayout(self.rejillaLayout) self.stack1 = QWidget() self.stack1UI() def stack1UI(self): for a in self.buttons['anticoagulant']: anticoag_rb = QRadioButton(a) self.anticoagButtongroup.addButton(anticoag_rb) self.dialogLayout.addWidget(anticoag_rb) for i in self.buttons['indication']: indication_rb = QRadioButton(i) self.indicationButtongroup.addButton(indication_rb) self.dialogLayout.addWidget(indication_rb) self.stack1.setLayout(self.dialogLayout) def cb_onclicked(self): if self.bridgingCheckBox.isChecked(): print('Puenteando') self.rejillaLayout.addWidget(self.stack1, 0, 2) self.stack1.show() self.adjustSize() else: print('No puenteando') self.rejillaLayout.removeWidget(self.stack1) self.stack1.hide() self.adjustSize() def UIcomponents(self): self.entries = {} formas = QFormLayout() for m in self.buttons['metrics']: if m != 'Sex?': ent = QLineEdit() formas.addRow(m, ent) self.entries[m] = ent # 修正原代码仅保存最后一个输入框的问题 else: self.sComboBox = QComboBox() self.sComboBox.addItems(self.buttons['sexo']) sLabel = QLabel('Sex:?') sLabel.setBuddy(self.sComboBox) formas.addRow(sLabel, self.sComboBox) self.entries['Sex?'] = self.sComboBox self.bridgingCheckBox = QCheckBox("Bridging dose") self.bridgingCheckBox.toggled.connect(self.cb_onclicked) formas.addRow(self.bridgingCheckBox, None) self.rejillaLayout.addLayout(formas, 0, 0) if __name__ == '__main__': app = QApplication(sys.argv) window = Window() window.setGeometry(50, 50, 300, 160) window.show() sys.exit(app.exec())
额外优化说明
- 修复了原代码中
self.entries仅保存最后一个输入框的逻辑错误,现在所有输入组件都被正确存储 - 移除了重复的导入语句,精简代码结构
- 去掉冗余的
self.sender()调用,直接访问self.bridgingCheckBox更简洁可靠
内容的提问来源于stack exchange,提问作者Lord_Amenegg
相关产品推荐
相关产品推荐

