From d49f2c2df71ae3e483564b68ca19b6a14bf22a55 Mon Sep 17 00:00:00 2001 From: David Stansby Date: Fri, 18 Mar 2022 17:50:50 +0000 Subject: [PATCH] Add scrollable widgets --- magicgui/backends/_qtpy/widgets.py | 18 ++++++++++++++++++ magicgui/widgets/_bases/container_widget.py | 9 +++++++++ magicgui/widgets/_protocols.py | 8 ++++++++ 3 files changed, 35 insertions(+) diff --git a/magicgui/backends/_qtpy/widgets.py b/magicgui/backends/_qtpy/widgets.py index fcf038070..b46971702 100644 --- a/magicgui/backends/_qtpy/widgets.py +++ b/magicgui/backends/_qtpy/widgets.py @@ -385,6 +385,24 @@ def __init__(self, layout="vertical"): else: self._layout = QtW.QVBoxLayout() self._qwidget.setLayout(self._layout) + # Create a scroll widget, but don't use it initially + self._scroll = QtW.QScrollArea() + # Allow widget to resize when window is larger than min widget size + self._scroll.setWidgetResizable(True) + + def _mgui_set_scrollable(self, scrollable: bool): + if scrollable == self._mgui_get_scrollable(): + return + + if scrollable: + # Transfer widget from MainWindow to ScrollArea + self._scroll.setWidget(self._qwidget) + self._qwidget = self._scroll + if not scrollable: + self._qwidget = self._scroll.takeWidget() + + def _mgui_get_scrollable(self): + return self._scroll.widget() is not None def _mgui_insert_widget(self, position: int, widget: Widget): self._layout.insertWidget(position, widget.native) diff --git a/magicgui/widgets/_bases/container_widget.py b/magicgui/widgets/_bases/container_widget.py index c554f02b9..9ef98828c 100644 --- a/magicgui/widgets/_bases/container_widget.py +++ b/magicgui/widgets/_bases/container_widget.py @@ -216,6 +216,15 @@ def layout(self, value): "It is not yet possible to change layout after instantiation" ) + @property + def scrollable(self) -> bool: + """Return if the widget can have scroll bars.""" + return self._widget._mgui_get_scrollable() + + @scrollable.setter + def scrollable(self, value: bool): + self._widget._mgui_set_scrollable(value) + def reset_choices(self, *_: Any): """Reset choices for all Categorical subWidgets to the default state. diff --git a/magicgui/widgets/_protocols.py b/magicgui/widgets/_protocols.py index 043994e3f..1d8c5ea09 100644 --- a/magicgui/widgets/_protocols.py +++ b/magicgui/widgets/_protocols.py @@ -450,6 +450,14 @@ def _mgui_get_margins(self) -> tuple[int, int, int, int]: def _mgui_set_margins(self, margins: tuple[int, int, int, int]) -> None: raise NotImplementedError() + @abstractmethod + def _mgui_get_scrollable(self) -> bool: + raise NotImplementedError() + + @abstractmethod + def _mgui_set_scrollable(self, scrollable: bool) -> None: + raise NotImplementedError() + class MainWindowProtocol(ContainerProtocol, Protocol): """Application main widget."""