Created
September 5, 2021 14:34
-
-
Save hanjinliu/4f79d9ecd0fca6c0760d4c0849307908 to your computer and use it in GitHub Desktop.
Convert a class into a QWidget and the methods into push buttons.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import annotations | |
import inspect | |
from magicgui import magicgui | |
import napari | |
from qtpy.QtWidgets import QPushButton, QWidget, QVBoxLayout | |
# Usage: | |
# >>> viewer = napari.Viewer() | |
# >>> cgui = ClassGui(viewer) | |
# >>> @cgui.from_class | |
# >>> class MyClass: | |
# >>> .... | |
# >>> viewer.window.add_dock_widget(cgui) | |
class ClassGui(QWidget): | |
def __init__(self, viewer:"napari.Viewer"=None): | |
if viewer is not None: | |
self.viewer = viewer | |
parent = viewer.window._qt_window | |
else: | |
parent = None | |
super().__init__(parent=parent) | |
self.setLayout(QVBoxLayout()) | |
self._current_dock_widget = None | |
self.base = None | |
def from_class(self, cls=None, *args, **kwargs): | |
""" | |
Make push buttons from a class. | |
""" | |
def wrap_class(cls): | |
self.base = cls(*args, **kwargs) | |
for name, f in inspect.getmembers(cls): | |
if name.startswith("_"): | |
continue | |
func = getattr(self.base, name) | |
if callable(func): | |
self.bind_method(func) | |
return cls | |
return wrap_class if cls is None else wrap_class(cls) | |
def bind_method(self, func, name=None): | |
""" | |
Make a push button from a class method. | |
""" | |
if not callable(func): | |
raise TypeError(f"{func} is not callable") | |
if name is None: | |
name = func.__name__.replace("_", " ") | |
button = QPushButton(name, parent=self) | |
button.setToolTip(func.__doc__) | |
def update_mgui(*args): | |
if self._current_dock_widget: | |
self.viewer.window.remove_dock_widget(self._current_dock_widget) | |
mgui = magicgui(func) | |
self._current_dock_widget = self.viewer.window.add_dock_widget(mgui, name=name) | |
self._current_dock_widget.setFloating(True) | |
return None | |
button.clicked.connect(update_mgui) | |
self.layout().addWidget(button) | |
return None | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment