如何独立于标题设置pyqtgraph Dock的最小宽度?
问题描述
我开发了一个包含多个堆叠Dock的应用程序,默认情况下Dock标签的最小宽度由其文本内容决定,这限制了DockArea的最小宽度,进而压缩了应用中其他内容的可用空间。我尝试修改pyqtgraph.dockarea.Dock.DockLabel和pyqtgraph.widgets.VerticalLabel的最小宽度为0,但并未看到效果。QTabWidget有usesScrollButtons属性,网页浏览器会独立于标签文本缩小标签宽度并仅显示标签开头部分,请问能否在pyqtgraph的Dock中实现类似效果?
复现问题的最小可运行代码:
import sys import pyqtgraph as pg from pyqtgraph.dockarea import Dock,DockArea from PyQt6.QtWidgets import QApplication,QWidget,QVBoxLayout class Foo(QWidget): """Contains minimal code to start, restore, initialize, and close the program. All high level logic is provided in separate and plugins.""" def __init__(self): super().__init__() lay = QVBoxLayout(self) self.mainDockArea = DockArea() lay.addWidget(self.mainDockArea) for i in range(10): dock = Dock(f'long title dock {i}',size=(10,10)) self.mainDockArea.addDock(dock,'below') if __name__ == '__main__': app = QApplication(sys.argv) mainWindow = Foo() mainWindow.show() sys.exit(app.exec())
解决方案
要实现类似QTabWidget的标签收缩+滚动效果,需要自定义修改Dock的标签容器和标签控件的行为,以下是可行的实现方式:
1. 自定义可收缩的DockLabel
重写DockLabel的尺寸提示方法,强制允许标签宽度被压缩,同时让文本超出时自动省略:
from pyqtgraph.dockarea import Dock from pyqtgraph.widgets.VerticalLabel import VerticalLabel from PyQt6.QtWidgets import QLabel from PyQt6.QtCore import Qt class ShrinkableDockLabel(Dock.DockLabel): def __init__(self, title, dock): super().__init__(title, dock) # 设置文本省略模式 if isinstance(self.label, QLabel): self.label.setElideMode(Qt.TextElideMode.ElideRight) elif isinstance(self.label, VerticalLabel): self.label.setElideMode(Qt.TextElideMode.ElideRight) def sizeHint(self): hint = super().sizeHint() # 限制标签的默认提示宽度,允许被压缩 hint.setWidth(min(hint.width(), 100)) return hint def minimumSizeHint(self): # 强制最小宽度为0,允许无限压缩 return super().minimumSizeHint().shrunkToWidth(0)
2. 替换Dock默认标签
创建自定义Dock类,使用上面的ShrinkableDockLabel替代原标签:
class ShrinkableDock(Dock): def __init__(self, title, *args, **kwargs): super().__init__(title, *args, **kwargs) # 替换默认标签为自定义收缩标签 self.label = ShrinkableDockLabel(title, self) self.titleBar.layout().insertWidget(0, self.label)
3. 修改主程序使用自定义Dock
将原代码中的Dock替换为ShrinkableDock即可实现标签收缩:
# 原循环部分修改为: for i in range(10): dock = ShrinkableDock(f'long title dock {i}', size=(10,10)) self.mainDockArea.addDock(dock,'below')
4. 实现标签滚动(可选)
如果需要类似QTabWidget的滚动按钮效果,需对DockArea的标题栏进行改造,核心逻辑如下:
from PyQt6.QtWidgets import QPushButton, QScrollArea def add_scroll_buttons(dock_area): # 获取DockArea的标题栏容器(需根据pyqtgraph实际结构调整) title_bar = dock_area.findChild(QWidget, 'dockAreaTitleBar') if not title_bar: return layout = title_bar.layout() if not isinstance(layout, QHBoxLayout): return # 创建滚动按钮 left_btn = QPushButton('<') right_btn = QPushButton('>') # 获取标签容器并包裹进滚动区域 tab_container = layout.itemAt(1).widget() scroll_area = QScrollArea() scroll_area.setWidget(tab_container) scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) # 替换布局中的标签容器 layout.replaceWidget(tab_container, scroll_area) # 绑定滚动事件 left_btn.clicked.connect(lambda: scroll_area.horizontalScrollBar().setValue(scroll_area.horizontalScrollBar().value() - 50)) right_btn.clicked.connect(lambda: scroll_area.horizontalScrollBar().setValue(scroll_area.horizontalScrollBar().value() + 50)) # 添加按钮到布局两端 layout.insertWidget(0, left_btn) layout.addWidget(right_btn)
在主程序初始化mainDockArea后调用该函数即可添加滚动按钮:
add_scroll_buttons(self.mainDockArea)
内容的提问来源于stack exchange,提问作者dukeeloo
相关产品推荐
相关产品推荐

