当一个小部件停靠时,我希望它改变方向并相对于扩展坞的扩展方式具有最小的尺寸。
那是,
- 左/右停靠 => 具有最小宽度的从上到下的方向
- 顶部/底部停靠 => 具有最小高度的从左到右方向
问题是,每当方向改变时,dock 就会出现看似任意的宽度或高度。停靠时,我找不到将停靠小部件调整大小/强制为特定大小的方法。我尝试了无数种覆盖sizeHint
, minimumSizeHint
, 调用adjustSize
和摆弄sizePolicy
.
如何确保初始坞站大小?
我的基本应用程序如下所示:
该应用程序显示主要和次要信息以及相应的控件集。包含主要和次要内容的选项卡小部件被设置为中央小部件。一个 QStackedWidget 容纳了各个仪表板中的控件,位于一个扩展坞中。当标签更改时,显示相应的仪表板。下面在基本应用程序代码中给出了此代码。
困难在于改变仪表板的方向会扰乱码头的尺寸。
调整仪表盘方向,我可以想到两个合理的解决方案:
- 通过
resizeEvent
或 - 通过
dockLocationChanged
信号
通过调整方向resizeEvent
在我看来,这似乎是更可取的选择。它为用户提供了最大的灵活性。如果他们不喜欢停靠点的方向,将其拖过特定限制将允许他们更改停靠点的方向。在这里,我检查它是否宽于高。
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)
下面在resize 方法中给出了完整的代码。
改变方向dockLocationChange
由于调整大小事件一直在发生,另一种方法可能是仅在停靠位置更改时更改方向。为此,请将功能连接到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)
基本应用代码
该计划由 5 个独立的课程组成。
为了
MyWindow
,PrimaryDashboard
, 和SecondaryDashboard
分离的原因应该足够清楚。
为了
MyDock
和DockContainer
分隔是为了便于覆盖sizeHint
,setDirection
或其他方法。
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_())
调整大小方法
此代码与基本应用程序代码相同,但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
方法
此代码与基本应用程序代码相同,但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_())