QDockWidget停靠状态下尺寸保存与恢复异常问题求助
QMainWindow停靠状态下QDockWidget尺寸无法恢复的解决方法
问题描述
使用QSettings结合saveState()/restoreState()保存恢复QMainWindow状态时,浮动的QDockWidget能完美恢复位置和尺寸,但停靠状态的QDockWidget仅能恢复位置,无法恢复尺寸。核心代码如下:
保存状态
# Save Actual settings configuration=QSettings("RBB", "MyLaps_CRI") configuration.setValue("geometry", self.saveGeometry()) configuration.setValue("windowState", self.saveState())
恢复状态
# Restore Setting Saved settings = QSettings("RBB", "MyLaps_CRI") if not settings.value("geometry") == None: self.restoreGeometry(settings.value("geometry")) if not settings.value("windowState") == None: self.restoreState(settings.value("windowState"))
问题原因与修复步骤
1. 修正QDockWidget初始化逻辑
你的Dock类未正确传递标题参数给父类,导致Qt无法准确识别并保存该停靠部件的状态。修改Dock类:
class Dock(QDockWidget): def __init__(self, title, parent=None): super(Dock, self).__init__(title, parent) # 正确传递标题参数 # 添加可视子部件,方便观察尺寸变化 label = QLabel(title, self) label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.setWidget(label)
2. 移除central widget子部件的固定尺寸
Classification_Show初始化时调用self.resize(1200,700)会强制部件大小,挤压停靠的QDockWidget。移除该固定尺寸,让布局自动适配:
class Classification_Show(QWidget): def __init__(self,parent): super().__init__() self.create_GUI() # 移除单独show(),子部件无需单独显示 # self.show() def create_GUI(self): """ Create GUI""" # 移除固定resize,依赖布局自适应 # self.resize(1200,700) self.setWindowTitle('Results') # ... 其余代码保持不变 ...
3. 给saveState/restoreState指定版本号
指定版本号可避免Qt版本兼容性问题,确保状态保存与恢复的一致性:
保存时
def closeEvent(self, event): print('closing') settings = QSettings("RBB", "MyLaps_CRI") settings.setValue('geometry', self.saveGeometry()) # 指定版本号1,恢复时需对应 settings.setValue('windowState', self.saveState(1)) super(Window, self).closeEvent(event)
恢复时
def readSettings(self): settings = QSettings("RBB", "MyLaps_CRI") geom = settings.value("geometry") if geom is not None: self.restoreGeometry(geom) state = settings.value("windowState") if state is not None: # 使用对应版本号恢复 self.restoreState(state, 1)
4. 设置QDockWidget的Size Policy
确保停靠状态下的部件允许拉伸,添加以下代码到CreateWidgets方法:
def CreateWidgets(self): self.firstDock_ = Dock('First', self) self.firstDock_.setObjectName('First') self.firstDock_.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, self.firstDock_) self.secondDock_ = Dock('Second', self) self.secondDock_.setObjectName('Second') self.secondDock_.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, self.secondDock_) # 其余dock部件同理设置Size Policy
完整修正后的测试代码
# coding = utf-8 import sys from PyQt6.QtCore import * from PyQt6.QtWidgets import * from PyQt6.QtGui import * class Classification_Show(QWidget): def __init__(self,parent): super().__init__() self.create_GUI() def create_GUI(self): """ Create GUI""" self.setWindowTitle('Results') # Set Colors palette = QPalette() brush = QBrush(QColor(255, 255, 127)) brush.setStyle(Qt.BrushStyle.SolidPattern) palette.setBrush(QPalette.ColorGroup.Active, QPalette.ColorRole.Base, brush) palette.setBrush(QPalette.ColorGroup.Active, QPalette.ColorRole.Window, brush) palette.setBrush(QPalette.ColorGroup.Disabled, QPalette.ColorRole.Base, brush) brush = QBrush(QColor(255, 0, 0)) palette.setBrush(QPalette.ColorGroup.Active, QPalette.ColorRole.WindowText, brush) self.setPalette(palette) # Create Table View of arrivals self.tv_arrival=QTableView() self.tv_arrival.setMinimumWidth(300) # Create Table View of Classificatiom self.tv_classification=QTableView() self.tv_classification.setMinimumWidth(300) # Create a Grid Layout layout=QGridLayout(self) # Set Font for text Rider Running font = QFont() font.setFamily('Calibri') font.setPointSize(8) widget_rider=QWidget(self) layout_rider=QGridLayout(widget_rider) # Create Box to show number is running self.rider_running_number=QLineEdit() self.rider_running_number.setMaximumWidth(50) self.rider_running_info=QLabel('') self.rider_running_info.setFont(font) self.rider_running_name=QLabel('Prubeas') self.rider_running_name.setFont(font) spacerItem = QSpacerItem(4000, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) # Show Logo(路径不存在时显示提示) self.logo_to_show=QLabel('') try: icon=QPixmap('C:/Roberto/Visual_Studio_Code/Rbenet/Cyclism/IMG/logo_fcc.png') ico=icon.scaledToWidth(100) self.logo_to_show.setPixmap(ico) except: self.logo_to_show.setText("Logo not found") layout_rider.addWidget(self.rider_running_number,1,1,1,1) layout_rider.addItem(spacerItem, 1, 2, 1, 1) layout_rider.addWidget(self.rider_running_name,1,3,1,1) layout_rider.addWidget(self.rider_running_info,1,4,1,1) layout_rider.addWidget(self.logo_to_show,1,5,1,1) # Set title of Table font.setPointSize(8) font.setBold(True) font.setUnderline(True) self.lb_arrival=QLabel('Llegas') self.lb_arrival.setFont(font) self.lb_classification=QLabel('Clasificaciones') self.lb_classification.setFont(font) self.lb_ddbb_name=QLabel('Pruebas') # tables and info in a Grid layout.addWidget(widget_rider,1,1,1,4) layout.addWidget(self.lb_arrival,2,1,1,1) layout.addWidget(self.lb_classification,2,3,1,4) layout.addWidget(self.tv_arrival,3,1,1,2) layout.addWidget(self.tv_classification,3,3,1,4) layout.addWidget(self.lb_ddbb_name,4,1,1,6) class Window(QMainWindow): def __init__(self, parent=None): super().__init__() # Set window size self.resize(600,400) self.setWindowTitle('Test Save Dock Widget') # Create Central Widget central_widget=QWidget() self.setCentralWidget(central_widget) # Create a Grid Layout layout=QGridLayout(central_widget) self.pb_stop_crono=QPushButton('Para Crono') self.pb_screen_2=QPushButton('Pantalla 2') self.le_capture=QLineEdit('') self.le_capture.setEnabled(False) layout.addWidget(self.pb_stop_crono,0,1,1,1) layout.addWidget(self.pb_screen_2,0,2,1,1) self.classification_show=Classification_Show(self) layout.addWidget(self.classification_show,1,1,1,2) layout.addWidget(self.le_capture,2,1,1,1) self.CreateWidgets() self.readSettings() self.show() def CreateWidgets(self): self.firstDock_ = Dock('First', self) self.firstDock_.setObjectName('First') self.firstDock_.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, self.firstDock_) self.secondDock_ = Dock('Second', self) self.secondDock_.setObjectName('Second') self.secondDock_.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, self.secondDock_) self.thirdDock_ = Dock('Third', self) self.thirdDock_.setObjectName('Third') self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, self.thirdDock_) self.thirdDock_.setFloating(True) self.fDock_ = Dock('Fourth', self) self.fDock_.setObjectName('Fourth') self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, self.fDock_) self.fDock_.setFloating(True) self.fiDock_ = Dock('Fifth', self) self.fiDock_.setObjectName('Fifth') self.fiDock_.setFloating(True) self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, self.fiDock_) def closeEvent(self, event): print('closing') settings = QSettings("RBB", "MyLaps_CRI") settings.setValue('geometry',self.saveGeometry()) settings.setValue('windowState',self.saveState(1)) super(Window, self).closeEvent(event) def readSettings(self): settings = QSettings("RBB", "MyLaps_CRI") geom = settings.value("geometry") if geom is not None: self.restoreGeometry(geom) state = settings.value("windowState") if state is not None: self.restoreState(state, 1) class Dock(QDockWidget): def __init__(self, title, parent=None): super(Dock, self).__init__(title, parent) label = QLabel(title, self) label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.setWidget(label) def main(): app = QApplication(sys.argv) app.setOrganizationName("RBB") app.setApplicationName("MyLaps_CRI") w = Window() sys.exit(app.exec()) if __name__ == '__main__': main()
内容的提问来源于stack exchange,提问作者RBenet
相关产品推荐
相关产品推荐

