简体   繁体   English

Qt:停靠小部件如何获得其初始大小?

[英]Qt: How does a dock widget get its initial size?

When a widget is docked, I would like it to change direction and have minimal size relative to how the dock expands. 将小部件停靠后,我希望它可以改变方向,并且相对于停靠件的扩展方式具有最小的尺寸。

That is, 那是,

  • left/right dock => top-to-bottom direction with minimum width 左/右基座=>上下方向且宽度最小
  • top/bottom dock => left-to-right direction with minimum height 顶部/底部基座=>左右方向且高度最小

The trouble is, whenever the direction is changed, the dock takes on a seemingly arbitrary width or height. 问题在于,无论方向如何改变,扩展坞都会呈现出看似任意的宽度或高度。 I cannot find a way to resize/force the dock widget to a particular size when docked. 我无法找到一种在停靠时将停靠小部件调整大小/强制使其达到特定大小的方法。 I have tried countless variations of overriding the sizeHint , minimumSizeHint , calling adjustSize , and fiddling with the sizePolicy . 我尝试了无数种方法来覆盖sizeHintminimumSizeHint ,调用adjustSize以及摆弄sizePolicy

How can I ensure the initial dock size? 我如何确保初始基座尺寸?


My basic application looks like: 我的基本应用程序如下所示:

在此处输入图片说明

The application shows primary and secondary information along with corresponding sets of controls. 该应用程序显示主要和辅助信息以及相应的控件集。 A tab widget containing the primary and secondary content is set as the Central Widget. 包含主要和次要内容的选项卡小部件被设置为中央小部件。 A QStackedWidget housing the controls in respective dashboards lives in a dock. 一个QStackedWidget分别位于各个仪表板中的控件中。 When the tab changes, the corresponding dashboard is shown. 当选项卡更改时,将显示相应的仪表板。 The code for this is given below in basic application code . 下面的基本应用程序代码中给出了此代码

The difficulty lies in that changing the direction of the dashboard upsets the size of the dock. 困难在于改变仪表板的方向会使底座的尺寸变大。

To adjust the dashboard direction, I can think of two reasonable solutions: 为了调整仪表板方向,我可以考虑两种合理的解决方案:

  • via the resizeEvent or 通过resizeEvent
  • via the dockLocationChanged signal 通过dockLocationChanged信号

Adjusting direction via resizeEvent 通过resizeEvent调整方向

This seems, to me, the preferable option. 在我看来,这似乎是更可取的选择。 It allows the user the most flexibility. 它为用户提供了最大的灵活性。 If they dislike the direction of a dock, dragging it past a particular limit will allow them to change the dock's direction. 如果他们不喜欢停靠的方向,则将其拖到特定的限制范围内将允许他们更改停靠的方向。 Here I check for whether it is wider than tall. 在这里,我检查它是否宽于高。

    class MyDock(QtWidgets.QDockWidget):

        def __init__(self):

            super(MyDock, self).__init__()

        def resizeEvent(self, event):
            size = event.size()
            is_wide = size.width() > size.height()

            container_object = self.widget().currentWidget()

            if is_wide:
                container_object.setDirection(QtWidgets.QBoxLayout.LeftToRight)
            else:
                container_object.setDirection(QtWidgets.QBoxLayout.TopToBottom)

The complete code for this is given below in resize approach . 完整的代码在下面以resize方法给出。

Change direction on dockLocationChange 更改dockLocationChange方向

As the resize event happens all the time, another approach might be to change the direction only when the dock location changes. 由于调整大小事件一直在发生,因此另一种方法可能是仅在坞站位置更改时才更改方向。 To do this, connect a function to the dockLocationChanged signal and adjust the direction depending on the dock. 为此,请将功能连接到dockLocationChanged信号,然后根据扩展坞调整方向。

    class MyDock(QtWidgets.QDockWidget):

        def __init__(self):

            super(MyDock, self).__init__()

            self.dockLocationChanged.connect(self.dock_location_changed)

        def dock_location_changed(self, area):
            top    = QtCore.Qt.DockWidgetArea.TopDockWidgetArea
            bottom = QtCore.Qt.DockWidgetArea.BottomDockWidgetArea

            container_object = self.widget().currentWidget()

            if area in [top, bottom]:
                container_object.setDirection(QtWidgets.QBoxLayout.LeftToRight)
            else:
                container_object.setDirection(QtWidgets.QBoxLayout.TopToBottom)

Basic application code 基本应用程式码

The program consists of 5 separate classes. 该程序包括5个单独的类。

For 对于

  1. MyWindow , MyWindow
  2. PrimaryDashboard , and PrimaryDashboard
  3. SecondaryDashboard

the reason for separation should be clear enough. 分离的原因应该足够清楚。

For 对于

  1. MyDock and MyDock
  2. DockContainer

the separation is to facilitate overriding sizeHint , setDirection , or other methods. 分离是为了便于覆盖sizeHintsetDirection或其他方法。

    import qtpy
    from qtpy import QtWidgets, QtGui, QtCore
    import sys


    class PrimaryDashboard(QtWidgets.QWidget):

        def __init__(self):

            super(PrimaryDashboard, self).__init__()

            self.init_widgets()
            self.init_layout()

        def init_widgets(self):
            self.label = QtWidgets.QLabel('Primary dashboard')
            self.ok = QtWidgets.QPushButton('OK')
            self.cancel = QtWidgets.QPushButton('Cancel')

        def init_layout(self):
            self.layout = QtWidgets.QHBoxLayout()
            self.layout.addWidget(self.label)
            self.layout.addWidget(self.ok)
            self.layout.addWidget(self.cancel)
            self.setLayout(self.layout)

        def setDirection(self, direction):
            self.layout.setDirection(direction)


    class SecondaryDashboard(QtWidgets.QWidget):

        def __init__(self):

            super(SecondaryDashboard, self).__init__()

            self.init_widgets()
            self.init_layout()

        def init_widgets(self):
            self.label = QtWidgets.QLabel('Secondary dashboard')

            self.descr1 = QtWidgets.QLabel('Thing 1')
            self.check1 = QtWidgets.QCheckBox()

            self.descr2 = QtWidgets.QLabel('Thing 2')
            self.check2 = QtWidgets.QCheckBox()

        def init_layout(self):
            self.layout = QtWidgets.QVBoxLayout()

            self.grid = QtWidgets.QGridLayout()
            self.grid.addWidget(self.descr1, 0, 0)
            self.grid.addWidget(self.check1, 0, 1)
            self.grid.addWidget(self.descr2, 1, 0)
            self.grid.addWidget(self.check2, 1, 1)

            self.layout.addWidget(self.label)
            self.layout.addLayout(self.grid)
            self.setLayout(self.layout)

        def setDirection(self, direction):
            self.layout.setDirection(direction)


    class DockContainer(QtWidgets.QStackedWidget):

        def __init__(self):

            super(DockContainer, self).__init__()


    class MyDock(QtWidgets.QDockWidget):

        def __init__(self):

            super(MyDock, self).__init__()


    class MyWindow(QtWidgets.QMainWindow):

        def __init__(self, parent=None):
            super(MyWindow, self).__init__(parent=parent)

            self.resize(600, 400)

            self.init_widgets()
            self.init_layout()

        def init_widgets(self):

            self.tab_widget = QtWidgets.QTabWidget()
            self.tab1 = QtWidgets.QLabel('Primary content')
            self.tab2 = QtWidgets.QLabel('Secondary content')
            self.tab_widget.addTab(self.tab1, 'Primary')
            self.tab_widget.addTab(self.tab2, 'Secondary')
            self.tab_widget.currentChanged.connect(self.tab_selected)

            self.primary_dashboard = PrimaryDashboard()
            self.secondary_dashboard = SecondaryDashboard()

            self.dashboard = DockContainer()
            self.dashboard.addWidget(self.primary_dashboard)
            self.dashboard.addWidget(self.secondary_dashboard)
            self.dashboard.setCurrentWidget(self.primary_dashboard)

            self.dock = MyDock()
            self.dock.setWidget(self.dashboard)
            self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.dock)

        def init_layout(self):
            self.main_layout = QtWidgets.QVBoxLayout()
            self.main_layout.addWidget(self.tab_widget)

            self.main_widget = QtWidgets.QWidget()
            self.main_widget.setLayout(self.main_layout)
            self.setCentralWidget(self.main_widget)

        def tab_selected(self):
            tab_index = self.tab_widget.currentIndex()
            if self.tab_widget.tabText(tab_index) == 'Secondary':
                self.dashboard.setCurrentWidget(self.secondary_dashboard)
                self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dock)
            else:  # Primary
                self.dashboard.setCurrentWidget(self.primary_dashboard)
                self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.dock)


    if __name__ == '__main__':
        app = QtWidgets.QApplication(sys.argv)

        window = MyWindow()
        window.show()
        sys.exit(app.exec_())

Resize approach 调整大小方法

This code is identical to the basic application code yet with resizeEvent overridden in the dock widget. 此代码与基本应用程序代码相同,但在坞站小部件中覆盖了resizeEvent

    import qtpy
    from qtpy import QtWidgets, QtGui, QtCore
    import sys


    class PrimaryDashboard(QtWidgets.QWidget):

        def __init__(self):

            super(PrimaryDashboard, self).__init__()

            self.init_widgets()
            self.init_layout()

        def init_widgets(self):
            self.label = QtWidgets.QLabel('Primary dashboard')
            self.ok = QtWidgets.QPushButton('OK')
            self.cancel = QtWidgets.QPushButton('Cancel')

        def init_layout(self):
            self.layout = QtWidgets.QHBoxLayout()
            self.layout.addWidget(self.label)
            self.layout.addWidget(self.ok)
            self.layout.addWidget(self.cancel)
            self.setLayout(self.layout)

        def setDirection(self, direction):
            self.layout.setDirection(direction)


    class SecondaryDashboard(QtWidgets.QWidget):

        def __init__(self):

            super(SecondaryDashboard, self).__init__()

            self.init_widgets()
            self.init_layout()

        def init_widgets(self):
            self.label = QtWidgets.QLabel('Secondary dashboard')

            self.descr1 = QtWidgets.QLabel('Thing 1')
            self.check1 = QtWidgets.QCheckBox()

            self.descr2 = QtWidgets.QLabel('Thing 2')
            self.check2 = QtWidgets.QCheckBox()

        def init_layout(self):
            self.layout = QtWidgets.QVBoxLayout()

            self.grid = QtWidgets.QGridLayout()
            self.grid.addWidget(self.descr1, 0, 0)
            self.grid.addWidget(self.check1, 0, 1)
            self.grid.addWidget(self.descr2, 1, 0)
            self.grid.addWidget(self.check2, 1, 1)

            self.layout.addWidget(self.label)
            self.layout.addLayout(self.grid)
            self.setLayout(self.layout)

        def setDirection(self, direction):
            self.layout.setDirection(direction)


    class DockContainer(QtWidgets.QStackedWidget):

        def __init__(self):

            super(DockContainer, self).__init__()


    class MyDock(QtWidgets.QDockWidget):

        def __init__(self):

            super(MyDock, self).__init__()

        def resizeEvent(self, event):
            size = event.size()
            is_wide = size.width() > size.height()

            container_object = self.widget().currentWidget()

            if is_wide:
                container_object.setDirection(QtWidgets.QBoxLayout.LeftToRight)
            else:
                container_object.setDirection(QtWidgets.QBoxLayout.TopToBottom)


    class MyWindow(QtWidgets.QMainWindow):

        def __init__(self, parent=None):
            super(MyWindow, self).__init__(parent=parent)

            self.resize(600, 400)

            self.init_widgets()
            self.init_layout()

        def init_widgets(self):

            self.tab_widget = QtWidgets.QTabWidget()
            self.tab1 = QtWidgets.QLabel('Primary content')
            self.tab2 = QtWidgets.QLabel('Secondary content')
            self.tab_widget.addTab(self.tab1, 'Primary')
            self.tab_widget.addTab(self.tab2, 'Secondary')
            self.tab_widget.currentChanged.connect(self.tab_selected)

            self.primary_dashboard = PrimaryDashboard()
            self.secondary_dashboard = SecondaryDashboard()

            self.dashboard = DockContainer()
            self.dashboard.addWidget(self.primary_dashboard)
            self.dashboard.addWidget(self.secondary_dashboard)
            self.dashboard.setCurrentWidget(self.primary_dashboard)

            self.dock = MyDock()
            self.dock.setWidget(self.dashboard)
            self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.dock)

        def init_layout(self):
            self.main_layout = QtWidgets.QVBoxLayout()
            self.main_layout.addWidget(self.tab_widget)

            self.main_widget = QtWidgets.QWidget()
            self.main_widget.setLayout(self.main_layout)
            self.setCentralWidget(self.main_widget)

        def tab_selected(self):
            tab_index = self.tab_widget.currentIndex()
            if self.tab_widget.tabText(tab_index) == 'Secondary':
                self.dashboard.setCurrentWidget(self.secondary_dashboard)
                self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dock)
            else:  # Primary
                self.dashboard.setCurrentWidget(self.primary_dashboard)
                self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.dock)


    if __name__ == '__main__':
        app = QtWidgets.QApplication(sys.argv)

        window = MyWindow()
        window.show()
        sys.exit(app.exec_())

dockLocationChanged approach dockLocationChanged方法

This code is identical to the basic application code yet with the dockLocationChanged signal connected to a method which adjusts the direction based on the current dock location. 该代码与基本应用程序代码相同,但将dockLocationChanged信号连接到根据当前停靠位置调整方向的方法。

    import qtpy
    from qtpy import QtWidgets, QtGui, QtCore
    import sys


    class PrimaryDashboard(QtWidgets.QWidget):

        def __init__(self):

            super(PrimaryDashboard, self).__init__()

            self.init_widgets()
            self.init_layout()

        def init_widgets(self):
            self.label = QtWidgets.QLabel('Primary dashboard')
            self.ok = QtWidgets.QPushButton('OK')
            self.cancel = QtWidgets.QPushButton('Cancel')

        def init_layout(self):
            self.layout = QtWidgets.QHBoxLayout()
            self.layout.addWidget(self.label)
            self.layout.addWidget(self.ok)
            self.layout.addWidget(self.cancel)
            self.setLayout(self.layout)

        def setDirection(self, direction):
            self.layout.setDirection(direction)


    class SecondaryDashboard(QtWidgets.QWidget):

        def __init__(self):

            super(SecondaryDashboard, self).__init__()

            self.init_widgets()
            self.init_layout()

        def init_widgets(self):
            self.label = QtWidgets.QLabel('Secondary dashboard')

            self.descr1 = QtWidgets.QLabel('Thing 1')
            self.check1 = QtWidgets.QCheckBox()

            self.descr2 = QtWidgets.QLabel('Thing 2')
            self.check2 = QtWidgets.QCheckBox()

        def init_layout(self):
            self.layout = QtWidgets.QVBoxLayout()

            self.grid = QtWidgets.QGridLayout()
            self.grid.addWidget(self.descr1, 0, 0)
            self.grid.addWidget(self.check1, 0, 1)
            self.grid.addWidget(self.descr2, 1, 0)
            self.grid.addWidget(self.check2, 1, 1)

            self.layout.addWidget(self.label)
            self.layout.addLayout(self.grid)
            self.setLayout(self.layout)

        def setDirection(self, direction):
            self.layout.setDirection(direction)


    class DockContainer(QtWidgets.QStackedWidget):

        def __init__(self):

            super(DockContainer, self).__init__()


    class MyDock(QtWidgets.QDockWidget):

        def __init__(self):

            super(MyDock, self).__init__()

            self.dockLocationChanged.connect(self.dock_location_changed)

        def dock_location_changed(self, area):
            top    = QtCore.Qt.DockWidgetArea.TopDockWidgetArea
            bottom = QtCore.Qt.DockWidgetArea.BottomDockWidgetArea
            # left   = QtCore.Qt.DockWidgetArea.LeftDockWidgetArea
            # right  = QtCore.Qt.DockWidgetArea.RightDockWidgetArea

            container_object = self.widget().currentWidget()

            if area in [top, bottom]:
                container_object.setDirection(QtWidgets.QBoxLayout.LeftToRight)
            else:
                container_object.setDirection(QtWidgets.QBoxLayout.TopToBottom)


    class MyWindow(QtWidgets.QMainWindow):

        def __init__(self, parent=None):
            super(MyWindow, self).__init__(parent=parent)

            self.resize(600, 400)

            self.init_widgets()
            self.init_layout()

        def init_widgets(self):

            self.tab_widget = QtWidgets.QTabWidget()
            self.tab1 = QtWidgets.QLabel('Primary content')
            self.tab2 = QtWidgets.QLabel('Secondary content')
            self.tab_widget.addTab(self.tab1, 'Primary')
            self.tab_widget.addTab(self.tab2, 'Secondary')
            self.tab_widget.currentChanged.connect(self.tab_selected)

            self.primary_dashboard = PrimaryDashboard()
            self.secondary_dashboard = SecondaryDashboard()

            self.dashboard = DockContainer()
            self.dashboard.addWidget(self.primary_dashboard)
            self.dashboard.addWidget(self.secondary_dashboard)
            self.dashboard.setCurrentWidget(self.primary_dashboard)

            self.dock = MyDock()
            self.dock.setWidget(self.dashboard)
            self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.dock)

        def init_layout(self):
            self.main_layout = QtWidgets.QVBoxLayout()
            self.main_layout.addWidget(self.tab_widget)

            self.main_widget = QtWidgets.QWidget()
            self.main_widget.setLayout(self.main_layout)
            self.setCentralWidget(self.main_widget)

        def tab_selected(self):
            tab_index = self.tab_widget.currentIndex()
            if self.tab_widget.tabText(tab_index) == 'Secondary':
                self.dashboard.setCurrentWidget(self.secondary_dashboard)
                self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dock)
            else:  # Primary
                self.dashboard.setCurrentWidget(self.primary_dashboard)
                self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.dock)


    if __name__ == '__main__':
        app = QtWidgets.QApplication(sys.argv)

        window = MyWindow()
        window.show()
        sys.exit(app.exec_())

Think of an application as a set of Matryoshka dolls . 可以将应用程序视为一套Matryoshka娃娃 An inner doll's size dictates that of the subsequent outer ones. 内部玩偶的大小决定了随后的外部玩偶的大小。 Clearly, an inner doll cannot be bigger than the one that contains it! 显然,一个内在的洋娃娃不能大于其中的一个! QWidgets are modeled similarly. QWidget的建模类似。

By default, composite widgets which do not provide a size hint will be sized according to the space requirements of their child widgets. 默认情况下,不提供大小提示的复合窗口小部件将根据其子窗口小部件的空间要求来调整大小。

The documentation for QWidget.sizeHint() goes on to say, QWidget.sizeHint()的文档继续说,

The default implementation of QWidget.sizeHint() returns an invalid size if there is no layout for this widget, and returns the layout's preferred size otherwise. 如果此小部件没有布局,则QWidget.sizeHint()的默认实现返回无效的大小,否则,返回布局的首选大小。

Altogether, a widget's sizing comes from the inside out, based on the layout. 总而言之, 小部件的大小是根据布局从内而外的。

If you were to implement a resizeEvent 1 for each of the objects in the base application code , you would see the following sequence of sizings, 如果要为基本应用程序代码中的每个对象实现resizeEvent 1 ,则会看到以下大小调整顺序,

  1. PrimaryDashboard resizeEvent PrimaryDashboard resizeEvent
  2. DockContainer resizeEvent DockContainer resizeEvent
  3. MyDock resizeEvent MyDock resizeEvent

This is the nesting we expect. 这是我们期望的嵌套。 The PrimaryDashboard is consulted first for its size, then the DockContainer , and then the MyDock . 首先查询PrimaryDashboard的大小,然后查询DockContainer ,然后查询MyDock Technically speaking, it's widgets all the way down. 从技术上讲,它一直是小部件。 However, the PrimaryDashboard contains buttons and labels which ought to be smaller than the width/height of the MainWindow in the majority of circumstances. 但是, PrimaryDashboard包含的按钮和标签在大多数情况下应小于MainWindow的宽度/高度。 The first doll in the sequence to significantly affect dock sizing is the PrimaryDashboard . 该序列中第一个会显着影响码头尺寸的玩偶是PrimaryDashboard

Examining the resizeEvent , using event.size() , we can see that a reasonable minimum for a horizontal dashboard is a height of 120 pixels whereas a vertical orientation has a reasonable minimum width of 146 . 使用event.size()检查resizeEvent ,我们可以看到水平仪表板的合理最小高度为120像素,而垂直方向的合理最小宽度为146 The sizeHint() can then be set to return the minimumSizeHint() and have the minimum return the (146, 120) for each of the dashboards 2 . 然后,可以将sizeHint()设置为返回minimumSizeHint() ,并使最小返回每个仪表板2(146, 120) In effect, this tells the application to prefer a minimum size of (146, 120) while still allowing for resizing in general. 实际上,这告诉应用程序首选最小大小为(146, 120)同时总体上仍允许调整大小。

def sizeHint(self):
    return self.minimumSizeHint()

def minimumSizeHint(self):
    return QtCore.QSize(146, 120)

Granted, using fixed sizing can be dangerous, as absolutes are unforgiving and not flexible by definition. 当然,使用固定大小可能会很危险,因为绝对值是不容忍的,并且根据定义不灵活。 However, the content likely has a natural minimum size 3 . 但是,内容可能具有自然的最小大小3 We can simply setMinimumSize() on the entire application to not allow resizing smaller than our minimumSizeHint() . 我们可以简单地在整个应用程序上设置setMinimumSize() ,以使其大小不能小于我们的minimumSizeHint()

To change the direction of the dock widget content, we can use the dockLocationChanged signal. 要更改dock小部件内容的方向,我们可以使用dockLocationChanged信号。 We can also make the code a little neater than how it was presented in the question. 我们还可以使代码比问题中的代码更加整洁。 Rather than connect the signal within the dock widget, we can connect it at the instance level within MyWindow . 可以在MyWindow的实例级别连接它,而不是在Dock小部件中连接信号。 In fact, there is no need to define MyDock at all. 实际上,根本不需要定义MyDock A plain QDockWidget will suffice. 一个简单的QDockWidget就足够了。

Docks with a minimal initial size 最小初始尺寸的船坞

import qtpy
from qtpy import QtWidgets, QtGui, QtCore
import sys


class PrimaryDashboard(QtWidgets.QWidget):

    def __init__(self):

        super(PrimaryDashboard, self).__init__()

        self.init_widgets()
        self.init_layout()

    def init_widgets(self):
        self.label = QtWidgets.QLabel('Primary dashboard')
        self.ok = QtWidgets.QPushButton('OK')
        self.cancel = QtWidgets.QPushButton('Cancel')

    def init_layout(self):
        self.layout = QtWidgets.QHBoxLayout()
        self.layout.addWidget(self.label)
        self.layout.addWidget(self.ok)
        self.layout.addWidget(self.cancel)
        self.setLayout(self.layout)

    def setDirection(self, direction):
        self.layout.setDirection(direction)

    def sizeHint(self):
        return self.minimumSizeHint()

    def minimumSizeHint(self):
        return QtCore.QSize(146, 120)


class SecondaryDashboard(QtWidgets.QWidget):

    def __init__(self):

        super(SecondaryDashboard, self).__init__()

        self.init_widgets()
        self.init_layout()

    def init_widgets(self):
        self.label = QtWidgets.QLabel('Secondary dashboard')

        self.descr1 = QtWidgets.QLabel('Thing 1')
        self.check1 = QtWidgets.QCheckBox()

        self.descr2 = QtWidgets.QLabel('Thing 2')
        self.check2 = QtWidgets.QCheckBox()

    def init_layout(self):
        self.layout = QtWidgets.QVBoxLayout()

        self.grid = QtWidgets.QGridLayout()
        self.grid.addWidget(self.descr1, 0, 0)
        self.grid.addWidget(self.check1, 0, 1)
        self.grid.addWidget(self.descr2, 1, 0)
        self.grid.addWidget(self.check2, 1, 1)

        self.layout.addWidget(self.label)
        self.layout.addLayout(self.grid)
        self.setLayout(self.layout)

    def setDirection(self, direction):
        self.layout.setDirection(direction)

    def sizeHint(self):
        return self.minimumSizeHint()

    def minimumSizeHint(self):
        return QtCore.QSize(146, 120)


class DockContainer(QtWidgets.QStackedWidget):

    def __init__(self):

        super(DockContainer, self).__init__()

    def dock_location_changed(self, area):
        top    = QtCore.Qt.DockWidgetArea.TopDockWidgetArea
        bottom = QtCore.Qt.DockWidgetArea.BottomDockWidgetArea

        container_object = self.currentWidget()

        if area in [top, bottom]:
            container_object.setDirection(QtWidgets.QBoxLayout.LeftToRight)
        else:
            container_object.setDirection(QtWidgets.QBoxLayout.TopToBottom)


class MyWindow(QtWidgets.QMainWindow):

    def __init__(self, parent=None):
        super(MyWindow, self).__init__(parent=parent)

        # Force minimumSize to ensure a sensible dashboard size
        self.setMinimumSize(QtCore.QSize(600, 400))

        self.init_widgets()
        self.init_layout()

    def init_widgets(self):

        self.tab_widget = QtWidgets.QTabWidget()
        self.tab1 = QtWidgets.QLabel('Primary content')
        self.tab2 = QtWidgets.QLabel('Secondary content')
        self.tab_widget.addTab(self.tab1, 'Primary')
        self.tab_widget.addTab(self.tab2, 'Secondary')
        self.tab_widget.currentChanged.connect(self.tab_selected)

        self.primary_dashboard = PrimaryDashboard()
        self.secondary_dashboard = SecondaryDashboard()

        self.dashboard = DockContainer()
        self.dashboard.addWidget(self.primary_dashboard)
        self.dashboard.addWidget(self.secondary_dashboard)
        self.dashboard.setCurrentWidget(self.primary_dashboard)

        self.dock = QtWidgets.QDockWidget()
        self.dock.setWidget(self.dashboard)
        self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.dock)

        # Connect signal at the main application level
        self.dock.dockLocationChanged.connect(self.dashboard.dock_location_changed)

    def init_layout(self):
        self.main_layout = QtWidgets.QVBoxLayout()
        self.main_layout.addWidget(self.tab_widget)

        self.main_widget = QtWidgets.QWidget()
        self.main_widget.setLayout(self.main_layout)
        self.setCentralWidget(self.main_widget)

    def tab_selected(self):
        tab_index = self.tab_widget.currentIndex()
        if self.tab_widget.tabText(tab_index) == 'Secondary':
            self.dashboard.setCurrentWidget(self.secondary_dashboard)
            self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dock)
        else:  # Primary
            self.dashboard.setCurrentWidget(self.primary_dashboard)
            self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.dock)


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)

    window = MyWindow()
    window.show()
    sys.exit(app.exec_())


1. How one might implement such a resizeEvent to see who is resizing: 1.如何实现这样的resizeEvent来查看谁正在调整大小:

    def resizeEvent(self, event):
        print('resizeEvent for ', self, flush=True)

2. A natural question is, "Why not simply set the sizeHint() to return the minimum size instead of calling minimumSizeHint() ? The best response I have is, "It don't work that way." Setting only the sizeHint() doesn't resize the dock to the minimum as you might expect. 2.一个自然的问题是, “为什么不简单地设置sizeHint()来返回最小大小,而不是调用minimumSizeHint()我得到的最佳答复是, “那样行不通。”仅设置sizeHint()不会将扩展坞的大小调整到最小。

The sizeHint() and minimumSizeHint() methods are virtual functions. sizeHint()minimumSizeHint()方法是虚函数。 My guess is that Qt has other functionality, which we're not privy to, that references these methods independently, requiring us to define things this way. 我的猜测是Qt还有其他我们不了解的功能,它们独立地引用这些方法,需要我们以这种方式定义事物。

3. If the content is a map, for example, it's unlikely the user would ever want the map to be 10px x 10px . 3.例如,如果内容是地图,则用户不太可能希望地图为10px x 10px Furthermore, it's a reasonable assumption that the user won't be working with a screen resolution less than 600 x 400 unless they're on mobile. 此外,合理的假设是,除非用户在移动设备上,否则其屏幕分辨率不会低于600 x 400 But if you're developing for mobile using PySide or PyQt5, there are some important questions you should be asking yourself, such as "Why?" 但是,如果您正在使用PySide或PyQt5开发移动设备,那么您应该问自己一些重要问题,例如“为什么?” .

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM