You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 20:32:01