如何使用大小提示正确定位 QDockWidgets

How to correctly position the QDockWidgets, with a size hint

如何根据给每个 dockwidgets 的大小提示在 QMainwindow 中正确定位不同的 Dockwidgets。我试图根据 addDockWidgetsetAllowedAreas 定位,但似乎我错过了这个概念。并在移动 QDockwidgets 时关闭标签化(防止它们在标签中分组)。

from PyQt5.QtWidgets import *
from PyQt5 import QtCore, QtGui
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys

class Dock_1(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
    
    def sizeHint(self):
        return QSize(.2*self.width(), .7*self.height()) 

class Dock_2(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
    
    def sizeHint(self):
        return QSize(.2*self.width(), .3*self.height()) 
    
class Dock_3(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
    
    def sizeHint(self):
        return QSize(.6*self.width(), .7*self.height()) 

class Dock_4(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
    
    def sizeHint(self):
        return QSize(.6*self.width(), .3*self.height()) 
    
class Dock_5(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
    
    def sizeHint(self):
        return QSize(.1*self.width(), self.height()) 
    
class Window(QMainWindow):
 
    def __init__(self):
        super().__init__()
        self.setGeometry(200, 200, 800, 800)
        self.UiComponents()
        self.show()
 
    def UiComponents(self):
        
        dock1 = QDockWidget("Dock_1", self)
        dock2 = QDockWidget("Dock_2", self)
        dock3 = QDockWidget("Dock_3", self)
        dock4 = QDockWidget("Dock_4", self)
        dock5 = QDockWidget("Dock_5", self)
        
        dock1.setAllowedAreas(Qt.LeftDockWidgetArea)
        dock2.setAllowedAreas(Qt.BottomDockWidgetArea)
        dock3.setAllowedAreas(Qt.TopDockWidgetArea)
        dock4.setAllowedAreas(Qt.BottomDockWidgetArea)
        dock5.setAllowedAreas(Qt.RightDockWidgetArea)

        w_1   = Dock_1(self)
        w_2   = Dock_2(self)
        w_3   = Dock_3(self)
        w_4   = Dock_4(self)
        w_5   = Dock_5(self) 

        dock1.setWidget(w_1)
        dock2.setWidget(w_2)
        dock3.setWidget(w_3)
        dock4.setWidget(w_4)
        dock5.setWidget(w_5)

        self.addDockWidget(Qt.LeftDockWidgetArea, dock1)
        self.addDockWidget(Qt.LeftDockWidgetArea, dock2)
        self.addDockWidget(Qt.RightDockWidgetArea, dock3)
        self.addDockWidget(Qt.RightDockWidgetArea, dock4)
        self.addDockWidget(Qt.RightDockWidgetArea, dock5)
        
 
App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec())

尺寸提示对于停靠小部件几乎没有用,因为中央小部件和主要 window 布局具有优先权,但是您的方法在任何情况下都是错误的,原因有两个:

  1. 大小提示在调整大小之前调用,并且基于当前大小返回提示是无效的,因为它可能导致某种递归(这不是通常会发生,因为 sizeHint() 通常仅在布局结构更改然后缓存时调用,但这不是重点);
  2. any 小部件初始化时,它具有默认大小(如果父级在构造函数中,则为 100x30,否则为 640x480),因此您的实现结果无论如何都是无效的;

因为你想要什么完全取决于主 window 的大小,唯一的可能性是调整 resizeEvent().

中的码头的大小

另请注意:

  • 为了并排放置停靠小部件,您必须使用 splitDockWidget();
  • 要使停靠栏 3 和 4 与 1 和 2(或 5)垂直对齐,您只能将它们放在(并允许)左侧或右侧停靠区域;
  • 允许的区域应与添加码头的区域相匹配;
  • 创建以主 window 作为父级的停靠栏的“内部”小部件毫无意义,因为停靠栏将取得该小部件的所有权;

考虑到以上情况,您应该删除所有 sizeHint() 覆盖,设置适当的允许区域,然后根据需要布置码头。

class Window(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setGeometry(200, 200, 800, 800)
        self.UiComponents()
        self.show()

    def UiComponents(self):
        dock1 = QDockWidget("Dock_1", self)
        dock2 = QDockWidget("Dock_2", self)
        dock3 = QDockWidget("Dock_3", self)
        dock4 = QDockWidget("Dock_4", self)
        dock5 = QDockWidget("Dock_5", self)

        dock1.setAllowedAreas(Qt.LeftDockWidgetArea)
        dock2.setAllowedAreas(Qt.LeftDockWidgetArea)
        dock3.setAllowedAreas(Qt.RightDockWidgetArea)
        dock4.setAllowedAreas(Qt.RightDockWidgetArea)
        dock5.setAllowedAreas(Qt.RightDockWidgetArea)

        w_1 = Dock_1()
        w_2 = Dock_2()
        w_3 = Dock_3()
        w_4 = Dock_4()
        w_5 = Dock_5()

        dock1.setWidget(w_1)
        dock2.setWidget(w_2)
        dock3.setWidget(w_3)
        dock4.setWidget(w_4)
        dock5.setWidget(w_5)

        self.addDockWidget(Qt.LeftDockWidgetArea, dock1)
        self.addDockWidget(Qt.LeftDockWidgetArea, dock2)
        self.addDockWidget(Qt.RightDockWidgetArea, dock3)
        self.addDockWidget(Qt.RightDockWidgetArea, dock4)
        self.addDockWidget(Qt.RightDockWidgetArea, dock5)

        self.splitDockWidget(dock1, dock2, Qt.Vertical)
        self.splitDockWidget(dock3, dock5, Qt.Horizontal)
        self.splitDockWidget(dock3, dock4, Qt.Vertical)

        self.docks = dock1, dock2, dock3, dock4, dock5

    def resizeEvent(self, event):
        super().resizeEvent(event)
        side = self.width() // 5 # 2 / 10
        center = side * 3 # 6 / 10
        widths = side, side, center, center, side
        self.resizeDocks(self.docks, widths, Qt.Horizontal)
        vUnit = self.height() // 10
        top = vUnit * 7
        bottom = vUnit * 3
        heights = top, bottom, top, bottom, top + bottom
        self.resizeDocks(self.docks, heights, Qt.Vertical)