如何在QDockWidget的可拖拽区域边界添加提示图标?
在PyQt5 DockWidget拖拽边界添加提示图标
嘿,我来帮你搞定这个需求——在DockWidgetArea之间的拖拽边界处加个提示图标,让用户一眼就知道这里可以拖拽调整大小。下面是修改后的完整代码,我会拆解关键部分帮你理解:
from PyQt5 import QtWidgets, QtCore, QtGui import sys class MainWindow(QtWidgets.QMainWindow): def __init__(self, parent=None): QtWidgets.QWidget.__init__(self, parent=parent) self.bgcolor = self.palette().color(self.backgroundRole()).name() self.central = QtWidgets.QTextEdit(self) self.central.setText('this is the central widget') self.setCentralWidget(self.central) self.setDockOptions(self.AnimatedDocks) #prevent tabbing self.rightDock = QtWidgets.QDockWidget('right dock', self) self.rightDock.setAllowedAreas(QtCore.Qt.RightDockWidgetArea) self.rightDock.setStyleSheet('QDockWidget::title{text-align:left;background:'+self.bgcolor+';}') self.everywhereDock = QtWidgets.QDockWidget('everywhere dock',self) self.everywhereDock.setAllowedAreas(QtCore.Qt.BottomDockWidgetArea | QtCore.Qt.TopDockWidgetArea | QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea) self.everywhereDock.setFeatures(QtWidgets.QDockWidget.DockWidgetFloatable | QtWidgets.QDockWidget.DockWidgetMovable) self.everywhereDock.setStyleSheet('QDockWidget::title{text-align:left;background:'+self.bgcolor+';}') self.dockable = QtWidgets.QTextEdit(self.rightDock) self.dockable.setText('this is dockable only on the right') self.dockable2 = QtWidgets.QTextEdit(self.everywhereDock) self.dockable2.setText('this is dockable everywhere, also its not closable') self.rightDock.setWidget(self.dockable) self.everywhereDock.setWidget(self.dockable2) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.rightDock) self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.everywhereDock) self.setTabPosition(QtCore.Qt.AllDockWidgetAreas, QtWidgets.QTabWidget.North) # 定义提示图标(用Qt自带的分割线图标,也可替换成自定义图标) self.horizontal_split_icon = self.style().standardIcon(QtGui.QStyle.SP_SplitHorizontal) self.vertical_split_icon = self.style().standardIcon(QtGui.QStyle.SP_SplitVertical) def paintEvent(self, event): super().paintEvent(event) painter = QtGui.QPainter(self) painter.setRenderHint(QtGui.QPainter.Antialiasing) # 获取中央组件的位置信息 central_geo = self.centralWidget().geometry() # 绘制右侧Dock与中央组件之间的垂直边界图标 right_dock_geo = self.rightDock.geometry() if right_dock_geo.isValid(): boundary_x = central_geo.right() icon_size = self.vertical_split_icon.actualSize(QtCore.QSize(24,24)) draw_x = boundary_x - icon_size.width() // 2 draw_y = (central_geo.top() + central_geo.bottom() - icon_size.height()) // 2 self.vertical_split_icon.paint(painter, draw_x, draw_y, icon_size.width(), icon_size.height()) # 绘制底部Dock与中央组件之间的水平边界图标 bottom_dock_geo = self.everywhereDock.geometry() if bottom_dock_geo.isValid(): boundary_y = central_geo.bottom() icon_size = self.horizontal_split_icon.actualSize(QtCore.QSize(24,24)) draw_x = (central_geo.left() + central_geo.right() - icon_size.width()) // 2 draw_y = boundary_y - icon_size.height() // 2 self.horizontal_split_icon.paint(painter, draw_x, draw_y, icon_size.width(), icon_size.height()) if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) m = MainWindow() m.show() sys.exit(app.exec_())
核心实现思路
- 图标选择:我用了Qt内置的分割线标准图标,你要是有自定义图标,直接把
self.style().standardIcon(...)换成QtGui.QIcon("你的图标路径.png")就行。 - 重写绘制事件:通过重写
paintEvent,在父类完成基础绘制后,用QPainter在拖拽边界上追加绘制提示图标。 - 精准定位:通过获取中央组件和Dock的位置信息,计算出边界线的坐标,再把图标放在边界的居中位置,确保提示醒目。
- 自适应更新:窗口调整大小、Dock位置变化时,
paintEvent会自动触发,图标会同步更新到正确位置,不用额外维护。
扩展提示
如果还有左侧、顶部的Dock区域,照着右侧、底部的逻辑复制即可:先获取对应Dock的几何信息,计算边界坐标,再绘制对应方向的图标。图标大小也可以调整,修改actualSize(QtCore.QSize(24,24))里的数值就行。
内容的提问来源于stack exchange,提问作者Jonas
相关产品推荐
相关产品推荐

