Generate multifunctional GUIs from classes

Overview

magic-class

In magicgui you can make simple GUIs from functions. However, we usually have to create GUIs that are composed of several buttons, and each button is connected with a class method.

Decorate your class with @magicclass and your can use the class both in GUI and from console!

magic-class is work in progress. Feel free to report issues and make suggestions 😄 .

Installation

  • use pip
pip install git+https://github.com/hanjinliu/magic-class
  • from source
git clone https://github.com/hanjinliu/magic-class

Example

Let's make a simple GUI that can load 1-D data and plot it.

from magicclass import magicclass
from pathlib import Path

@magicclass
class PlotData:
    """
    Load 1D data and plot it.
    """
    def __init__(self, title=None):
        self.title = title
        self.data = None
        self.path = None
        
    def load(self, path:Path):
        """
        Load file.
        """
        self.path = str(path)
        self.data = np.loadtxt(path)
        
    def plot(self):
        """
        Plot data.
        """
        if self.title:
            plt.title(self.title)
        plt.plot(self.data)
        plt.show()

Classes decorated with @magicclass are converted to magicgui's Container widgets. GUI starts with show method.

widget = PlotData(title="Title")
widget.show()

You can continue analysis in console.

widget.plot()

magic-class is also compatible with napari. You can add them to viewers as dock widgets.

import napari
viewer = napari.Viewer()
viewer.window.add_dock_widget(widget)

Other examples are in the "examples" folder.

Comments
  • using magicclass and popup boxes

    using magicclass and popup boxes

    Hi @hanjinliu Thanks for this amazing tool. I've been enjoying playing around with it.

    I was looking at this example using pandas and seaborn When clicking each button, a popup window appears. image

    Instead of a popup window, how can I have the fields appear in the main window (in this case, above the Swarm Plot button)? Also, my aim is that once the user enters the values within the main window and clicks the Swarm Plot button it just plots it using the values without an additional box?

    I can see you've used field or magicgui before, but where do I add that if I was following a similar workflow as your seaborn example?

    Cheers Pradeep

    opened by pr4deepr 13
  • Table widget parameters and methods

    Table widget parameters and methods

    Hi @hanjinliu, I have a Table widget in my magicclass GUI created using field. I would like to limit the maximum value (int or float) that can be entered in any of the table's cells. Also, I would like to update a plot embedded in the GUI every time any of the table's values is changed. I looked at the documentation of magicgui/magiclass but could not find info on this widget. Could you point at something regarding this? Thanks!

    opened by GiuseppeCiccone96 8
  • Help with crating child class containing Matplotlib plots

    Help with crating child class containing Matplotlib plots

    Hi,

    I am trying to create a child class called PlotData (groupbox) containing 2 plots. This is my code:

    #Child
    	@magicclass(name="Plots",layout="horizontal",widget_type="groupbox")
    	class PlotData: 
    		#plot widgets in child class 
    		plt = field(Figure, options={"nrows": 1, "ncols": 1})
    		plt1 = field(Figure, options={"nrows": 1, "ncols": 1})
    		def plot_storage_modulus(self):
    			self.plt.axes[0].set_yscale('log')
    			self.plt.axes[0].set_xscale('log')
    			for i in range(self.num_tests-1):
    				#set log scale
    				self.plt.axes[0].plot(self.data['strain [%]'][i], self.data['storage modulus [Pa]'][i], '-s')
    				self.plt.draw()
    		
    		def plot_loss_modulus(self):
    			self.plt1.axes[0].set_yscale('log')
    			self.plt1.axes[0].set_xscale('log')
    			for i in range(self.num_tests-1):
    				#set log scale
    				self.plt1.axes[0].plot(self.data['strain [%]'][i], self.data['loss modulus [Pa]'][i], '-o')
    				self.plt1.draw()
    	
    
    	@PlotData.wraps
    	def plot_storage_modulus(self):
    	      self.plt.axes[0].set_yscale('log')
    	      self.plt.axes[0].set_xscale('log')
    	      for i in range(self.num_tests-1):
    		      #set log scale
    		      self.plt.axes[0].plot(self.data['strain [%]'][i], self.data['storage modulus [Pa]'][i], '-s')
    		      self.plt.draw()
    
    	@PlotData.wraps
    	def plot_loss_modulus(self):
    		self.plt1.axes[0].set_yscale('log')
    		self.plt1.axes[0].set_xscale('log')
    		for i in range(self.num_tests-1):
    			#set log scale
    			self.plt1.axes[0].plot(self.data['strain [%]'][i], self.data['loss modulus [Pa]'][i], '-o')
    			self.plt1.draw()
    

    however I get an error message saying that the "ParentClass has no attribute plt". This makes sense as the plt field was defined inside the child class PlotData. How can I avert this issue? If I define the plf field in the parent class, then 4 plots appear (2 from the parent and 2 from the child). Thanks a lot :)

    opened by GiuseppeCiccone96 8
  • NameError: name 'pyqtgraph' is not defined

    NameError: name 'pyqtgraph' is not defined

    Hi I'm using magicclass for writing a UI for napari plugin and it was working fine. But, recently I amgetting this error:

    NameError: name 'pyqtgraph' is not defined

    Does the error log help for debugging?

    Error Log

    
    NameError                                 Traceback (most recent call last)
    ~\.conda\envs\llsz_napari\lib\site-packages\napari_plugin_engine\manager.py in _load_and_register(self=, mod_name='llsz', plugin_name='llsz_napari')
        317         try:
    --> 318             module = load(mod_name)
            module = undefined
            global load = 
            mod_name = 'llsz'
        319             if self.is_registered(module):
    
    ~\.conda\envs\llsz_napari\lib\site-packages\napari_plugin_engine\manager.py in load(value='llsz')
       1041         raise ValueError(f"malformed entry point string: {value}")
    -> 1042     module = importlib.import_module(match.group('module'))
            module = undefined
            global importlib.import_module = 
            match.group = 
       1043     attrs = filter(None, (match.group('attr') or '').split('.'))
    
    ~\.conda\envs\llsz_napari\lib\importlib\__init__.py in import_module(name='llsz', package=None)
        126             level += 1
    --> 127     return _bootstrap._gcd_import(name[level:], package, level)
            global _bootstrap._gcd_import = 
            name = 'llsz'
            level = 0
            package = None
        128 
    
    ~\.conda\envs\llsz_napari\lib\importlib\_bootstrap.py in _gcd_import(name='llsz', package=None, level=0)
    
    ~\.conda\envs\llsz_napari\lib\importlib\_bootstrap.py in _find_and_load(name='llsz', import_=)
    
    ~\.conda\envs\llsz_napari\lib\importlib\_bootstrap.py in _find_and_load_unlocked(name='llsz', import_=)
    
    ~\.conda\envs\llsz_napari\lib\importlib\_bootstrap.py in _load_unlocked(spec=ModuleSpec(name='llsz', loader=
    
    ~\.conda\envs\llsz_napari\lib\importlib\_bootstrap_external.py in exec_module(self=, module=)
    
    ~\.conda\envs\llsz_napari\lib\importlib\_bootstrap.py in _call_with_frames_removed(f=, *args=( at 0x00000185D237F240, fil...z_repo\llsz_napari\src\llsz\__init__.py", line 2>, {'__builtins__': {'ArithmeticError': , 'AssertionError': , 'AttributeError': , 'BaseException': , 'BlockingIOError': , 'BrokenPipeError': , 'BufferError': , 'BytesWarning': , 'ChildProcessError': , 'ConnectionAbortedError': , ...}, '__cached__': r'd:\onedrive - wehi.edu.au\wehi_projects\lightshe...pari\src\llsz\__pycache__\__init__.cpython-38.pyc', '__doc__': None, '__file__': r'd:\onedrive - wehi.edu.au\wehi_projects\lightsheet\llsz_repo\llsz_napari\src\llsz\__init__.py', '__loader__': , '__name__': 'llsz', '__package__': 'llsz', '__path__': [r'd:\onedrive - wehi.edu.au\wehi_projects\lightsheet\llsz_repo\llsz_napari\src\llsz'], '__spec__': ModuleSpec(name='llsz', loader=
    
    d:\onedrive - wehi.edu.au\wehi_projects\lightsheet\llsz_repo\llsz_napari\src\llsz\__init__.py in 
          6 #from ._writer import napari_get_writer, napari_write_image
    ----> 7 from llsz.ui import napari_experimental_provide_dock_widget
            global llsz.ui = undefined
            global napari_experimental_provide_dock_widget = undefined
          8 #from llsz.ui_widget_test import napari_experimental_provide_dock_widget
    
    d:\onedrive - wehi.edu.au\wehi_projects\lightsheet\llsz_repo\llsz_napari\src\llsz\ui.py in 
          6 
    ----> 7 from magicclass.wrappers import set_design
            global magicclass.wrappers = undefined
            global set_design = undefined
          8 from magicgui import magicgui
    
    ~\.conda\envs\llsz_napari\lib\site-packages\magicclass\__init__.py in 
          2 
    ----> 3 from .core import (
            global core = undefined
            global magicclass = undefined
            global magicmenu = undefined
            global magiccontext = undefined
            global magictoolbar = undefined
            global Parameters = undefined
            global Bound = undefined
            global build_help = undefined
          4     magicclass,
    
    ~\.conda\envs\llsz_napari\lib\site-packages\magicclass\core.py in 
         12 
    ---> 13 from .gui.class_gui import (
            global gui.class_gui = undefined
            global ClassGuiBase = undefined
            global ClassGui = undefined
            global GroupBoxClassGui = undefined
            global MainWindowClassGui = undefined
            global SubWindowsClassGui = undefined
            global ScrollableClassGui = undefined
            global DraggableClassGui = undefined
            global ButtonClassGui = undefined
            global CollapsibleClassGui = undefined
            global HCollapsibleClassGui = undefined
            global SplitClassGui = undefined
            global TabbedClassGui = undefined
            global StackedClassGui = undefined
            global ToolBoxClassGui = undefined
            global ListClassGui = undefined
         14     ClassGuiBase,
    
    ~\.conda\envs\llsz_napari\lib\site-packages\magicclass\gui\__init__.py in 
    ----> 1 from ._base import BaseGui, MagicTemplate
            global _base = undefined
            global BaseGui = undefined
            global MagicTemplate = undefined
          2 from .class_gui import ClassGui
          3 from .menu_gui import MenuGui, MenuGuiBase, ContextMenuGui
    
    ~\.conda\envs\llsz_napari\lib\site-packages\magicclass\gui\_base.py in 
         22 from .keybinding import as_shortcut
    ---> 23 from .mgui_ext import AbstractAction, Action, FunctionGuiPlus, PushButtonPlus, _LabeledWidgetAction, mguiLike
            global mgui_ext = undefined
            global AbstractAction = undefined
            global Action = undefined
            global FunctionGuiPlus = undefined
            global PushButtonPlus = undefined
            global _LabeledWidgetAction = undefined
            global mguiLike = undefined
         24 from .utils import get_parameters, define_callback
    
    ~\.conda\envs\llsz_napari\lib\site-packages\magicclass\gui\mgui_ext.py in 
         14 from matplotlib.colors import to_rgb
    ---> 15 from ..widgets import Separator
            global widgets = undefined
            global Separator = undefined
         16 
    
    ~\.conda\envs\llsz_napari\lib\site-packages\magicclass\widgets\__init__.py in 
         42 
    ---> 43 from .qtgraph import *
            global qtgraph = undefined
         44 from .napari import *
    
    ~\.conda\envs\llsz_napari\lib\site-packages\magicclass\widgets\qtgraph\__init__.py in 
         31 
    ---> 32 del pyqtgraph
            global pyqtgraph = undefined
         33 
    
    NameError: name 'pyqtgraph' is not defined
    
    The above exception was the direct cause of the following exception:
    
    PluginImportError                         Traceback (most recent call last)
    ~\.conda\envs\llsz_napari\lib\site-packages\napari_plugin_engine\manager.py in discover(self=, path=None, entry_point=None, prefix=None, ignore_errors=True)
        262 
        263             try:
    --> 264                 if self._load_and_register(mod_name, name):
            self._load_and_register = >
            mod_name = 'llsz'
            name = 'llsz_napari'
        265                     count += 1
        266                     self._id_counts[name] = 1
    
    ~\.conda\envs\llsz_napari\lib\site-packages\napari_plugin_engine\manager.py in _load_and_register(self=, mod_name='llsz', plugin_name='llsz_napari')
        320                 return None
        321         except Exception as exc:
    --> 322             raise PluginImportError(
            global PluginImportError = 
            plugin_name = 'llsz_napari'
            global cause = undefined
            exc = undefined
        323                 f'Error while importing module {mod_name}',
        324                 plugin_name=plugin_name,
    
    PluginImportError: Error while importing module llsz
    ================================================================================
    
    opened by pr4deepr 5
  • cannot import click error

    cannot import click error

    Hi I installed magicclass using pip install git+https://github.com/hanjinliu/magic-class.git

    When running from magicclass import click

    I get this error: cannot import name 'click' from 'magicclass'

    It was working from the pip release, but I was getting some errors, hence the reason I installed from the updated master branch instead.

    Cheers Pradeep

    opened by pr4deepr 4
  • Problem to run any example

    Problem to run any example

    Hi,

    I tried to run any of the example on my Python 3.8 on a Ubuntu 20.04 but get always errors like this:

    /home/sebi06/miniconda3/envs/imageanalysis_czi/bin/python /datadisk1/tuxedo/Github/magic-class/examples/advanced/graph_viewer.py
    Traceback (most recent call last):
      File "/datadisk1/tuxedo/Github/magic-class/examples/advanced/graph_viewer.py", line 1, in 
        from magicclass import magicclass, field, click, magicmenu, magiccontext
      File "/datadisk1/tuxedo/Github/magic-class/magicclass/__init__.py", line 3, in 
        from .core import (magicclass, magicmenu, magiccontext, WidgetType, Parameters, Bound, 
      File "/datadisk1/tuxedo/Github/magic-class/magicclass/core.py", line 11, in 
        from macrokit import Expr, register_type, Head
      File "/home/sebi06/miniconda3/envs/imageanalysis_czi/lib/python3.8/site-packages/macrokit/__init__.py", line 4, in 
        from .expression import Expr, Head, symbol
      File "/home/sebi06/miniconda3/envs/imageanalysis_czi/lib/python3.8/site-packages/macrokit/expression.py", line 8, in 
        from ._validator import validator
      File "/home/sebi06/miniconda3/envs/imageanalysis_czi/lib/python3.8/site-packages/macrokit/_validator.py", line 37, in 
        validator = Validator[Head, list[Any]]()
    TypeError: 'type' object is not subscriptable
    
    Process finished with exit code 1

    Any hint what I am doing wrong here?

    opened by sebi06 4
  • Input widgets for class attributes  with type declarations as in magicgui?

    Input widgets for class attributes with type declarations as in magicgui?

    Dear @hanjinliu ,

    thanks, this looks great.

    One question: is it also possible to keep input widgets for numbers, data, etc. as in magicgui or is it currently restricted to generating buttons that trigger method calls?

    Maybe these could be class attributes with a magicgu-like wrapper?

    If we can set properties of the class that could be quite useful.

    opened by VolkerH 4
  • `WidgetOptions` being removed

    `WidgetOptions` being removed

    hey @hanjinliu, I removed magicgui.types.WidgetOptions, which you import in various places outside of a TYPE_CHECKING clause.

    I can put it back in, but I would be doing so only to avoid breaking your stuff. If you're just importing for the sake of type hints, I would recommend using:

    if TYPE_CHECKING:
        from magicgui.types import WidgetOptions
    

    I see a number of other private imports (such as from widgets._concrete) and just wanted to give you a heads up that I would like to be reorganizing a number of things, most of which were private, and these will probably break some of your stuff. You might be better off vendoring (i.e. copying into this repo) any of the private things that you would like to use here.

    opened by tlambert03 3
  • callbacks in nested classes

    callbacks in nested classes

    Hi I am trying to use callbacks within magicclass and running into errors..

    When I try this, it works with no problem:

    from magicclass import magicclass, vfield
    
    @magicclass
    class MyClass:
            a = vfield(int, options={"value": 30},name = "Deskew Angle")
    
            @a.connect
            def _callback(self):
                print("value changed!",self.a)
    ui = MyClass()
    ui.show()
    

    However, when I use nested classes and try to use callbacks, I get an error:

    from magicclass import magicclass, vfield

    @magicclass
    class MyClass:
        @magicclass
        class MyClass1:
            a = vfield(int, options={"value": 30},name = "Deskew Angle")
    
            @a.connect
            def _callback(self):
                print("value changed!",self.a)
    ui = MyClass()
    ui.show()
    

    ERROR:


    ValueError Traceback (most recent call last) D:\Anaconda3\envs\llsz_py39\lib\site-packages\magicclass\gui\class_gui.py in _convert_attributes_into_widgets(self) 102 # If MagicField is given by field() function. --> 103 widget = self._create_widget_from_field(name, attr) 104

    D:\Anaconda3\envs\llsz_py39\lib\site-packages\magicclass\gui\class_gui.py in _create_widget_from_field(self, name, fld) 59 # funcname = callback.name ---> 60 widget.changed.connect(define_callback(self, callback)) 61

    D:\Anaconda3\envs\llsz_py39\lib\site-packages\magicclass\gui\utils.py in define_callback(self, callback) 12 def define_callback(self: BaseGui, callback: Callable): ---> 13 clsname, funcname = callback.qualname.split(".") 14 def _callback():

    ValueError: too many values to unpack (expected 2)

    The above exception was the direct cause of the following exception:

    MagicClassConstructionError Traceback (most recent call last) ~\AppData\Local\Temp/ipykernel_23928/3118444370.py in 10 def _callback(self): 11 print("value changed!",self.a) ---> 12 ui = MyClass() 13 ui.show()

    D:\Anaconda3\envs\llsz_py39\lib\site-packages\magicclass\core.py in init(self, *args, **kwargs) 205 ) 206 super(oldclass, self).init(*args, **kwargs) --> 207 self._convert_attributes_into_widgets() 208 209 if hasattr(self, _POST_INIT):

    D:\Anaconda3\envs\llsz_py39\lib\site-packages\magicclass\gui\class_gui.py in _convert_attributes_into_widgets(self) 213 if isinstance(e, MagicClassConstructionError): 214 e.args = (f"\n{hist_str}\n{e}",) --> 215 raise e 216 else: 217 raise MagicClassConstructionError(f"\n{hist_str}\n\n{type(e).name}: {e}") from e

    D:\Anaconda3\envs\llsz_py39\lib\site-packages\magicclass\gui\class_gui.py in _convert_attributes_into_widgets(self) 92 if isinstance(attr, type): 93 # Nested magic-class ---> 94 widget = attr() 95 setattr(self, name, widget) 96

    D:\Anaconda3\envs\llsz_py39\lib\site-packages\magicclass\core.py in init(self, *args, **kwargs) 205 ) 206 super(oldclass, self).init(*args, **kwargs) --> 207 self._convert_attributes_into_widgets() 208 209 if hasattr(self, _POST_INIT):

    D:\Anaconda3\envs\llsz_py39\lib\site-packages\magicclass\gui\class_gui.py in _convert_attributes_into_widgets(self) 215 raise e 216 else: --> 217 raise MagicClassConstructionError(f"\n{hist_str}\n\n{type(e).name}: {e}") from e 218 219

    MagicClassConstructionError:

      MyClass1 (ABCMeta) <--- Error
    
    
      a (MagicValueField) <--- Error
    

    ValueError: too many values to unpack (expected 2)

    I have the latest version of magicclass installed... Is there an error with how I'm using this functionality??

    Thanks Pradeep

    opened by pr4deepr 3
  • Trouble creating magic-class with two functions, each decorated with @magicgui

    Trouble creating magic-class with two functions, each decorated with @magicgui

    We are updating some older magic-class code we used to control a microscope with napari. In the process, we discovered that our GUI is no longer being rendered correctly in napari. That led to some testing and questions on my part.

    My main question is how do I create two functions in a magic-class, each decorator with magicgui options?

    For example, I would expect this code,

    from magicclass import magicclass
    from magicgui import magicgui
    
    # Test magicgui options      
    @magicclass(labels=False,name='Test two magicgui')
    class TestTwoMagicgui:
    
        # initialize
        def __init__(self):
            self.value_1 = 25
            self.value_2 = 400
            self.value_3 = 0
    
        @magicgui(layout='horizontal',
                  value_1={"widget_type": "FloatSpinBox", "min": 5, "max": 225, "label": 'Value 1'},
                  call_button = 'Set value 1')
        def set_value_1(self, value_1 = 25.0):
            """
            Set value 1
    
            :param value_1: float
    
            :return None:
            """
    
            self.value_1=value_1
    
        @magicgui(layout='horizontal',
                  value_2 = {"widget_type": "SpinBox",  "min": 0, "max": 100, "label": 'Value 2'},
                  value_3 = {"widget_type": "FloatSpinBox", "min": 0.0, "max": 200.0, "label": 'Value 3'},
                  call_button = "Set values 2 and 3"
                 )
        def set_values_2_3(self, value_2= 50, value_3 = 10.0):
            """
            Set values 2 and 3
    
            :param value_2: int
            :param value_3: float
    
            :return None:
            """
    
            self.value_2 = value_2
            self.value_3 = value_3
    
    if __name__ == "__main__":
        ui = TestTwoMagicgui()
        ui.show()
    

    To show a GUI with two widgets. The first widget should have one entry and the second widget have two entries. Instead, I get a blank GUI that I have to expand to see the title of the window (screenshot attached).

    image

    Do you have any suggestions about how to properly setup the above magic-class?

    Thanks!

    bug 
    opened by AlexCoul 2
  • move_to_center failing in certain cases

    move_to_center failing in certain cases

    just a heads up. the recent move_to_center commit is failing in certain cases (seen in magicgui tests)... will remove the magic-class tests for now:

    platform linux -- Python 3.10.6, pytest-7.1.3, pluggy-1.0.0 -- /opt/hostedtoolcache/Python/3.10.6/x64/bin/python
    [22](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:23)
    cachedir: .pytest_cache
    [23](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:24)
    PyQt5 5.15.7 -- Qt runtime 5.15.2 -- Qt compiled 5.15.2
    
    _______________________________ test_progressbar _______________________________
    [163](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:164)
    CALL ERROR: Exceptions caught in Qt event loop:
    [164](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:165)
    ________________________________________________________________________________
    [165](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:166)
    Traceback (most recent call last):
    [166](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:167)
      File "/home/runner/work/magicgui/magicgui/magic-class/magicclass/utils/qthreading.py", line 793, in init_pbar
    [167](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:168)
        pbar.show()
    [168](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:169)
      File "/home/runner/work/magicgui/magicgui/magic-class/magicclass/utils/qthreading.py", line 330, in show
    [169](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:170)
        move_to_screen_center(self._CONTAINER)
    [170](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:171)
      File "/home/runner/work/magicgui/magicgui/magic-class/magicclass/utils/qt.py", line 77, in move_to_screen_center
    [171](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:172)
        qwidget.move(screen_center() - qwidget.rect().center())
    [172](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:173)
      File "/opt/hostedtoolcache/Python/3.10.6/x64/lib/python3.10/site-packages/magicgui/widgets/_bases/container_widget.py", line 88, in __getattr__
    [173](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:174)
        return object.__getattribute__(self, name)
    [174](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:175)
    AttributeError: 'ScrollableContainer' object has no attribute 'move'
    [175](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:176)
    ________________________________________________________________________________
    [176](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:177)
    ----------------------------- Captured stderr call -----------------------------
    [177](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:178)
    Exceptions caught in Qt event loop:
    [178](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:179)
    ________________________________________________________________________________
    [179](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:180)
    Traceback (most recent call last):
    [180](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:181)
      File "/home/runner/work/magicgui/magicgui/magic-class/magicclass/utils/qthreading.py", line 793, in init_pbar
    [181](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:182)
        pbar.show()
    [182](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:183)
      File "/home/runner/work/magicgui/magicgui/magic-class/magicclass/utils/qthreading.py", line 330, in show
    [183](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:184)
        move_to_screen_center(self._CONTAINER)
    [184](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:185)
      File "/home/runner/work/magicgui/magicgui/magic-class/magicclass/utils/qt.py", line 77, in move_to_screen_center
    [185](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:186)
        qwidget.move(screen_center() - qwidget.rect().center())
    [186](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:187)
      File "/opt/hostedtoolcache/Python/3.10.6/x64/lib/python3.10/site-packages/magicgui/widgets/_bases/container_widget.py", line 88, in __getattr__
    [187](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:188)
        return object.__getattribute__(self, name)
    [188](https://github.com/napari/magicgui/actions/runs/3077835365/jobs/4972976813#step:7:189)
    AttributeError: 'ScrollableContainer' object has no attribute 'move'
    
    
    opened by tlambert03 2
  • Support `async`

    Support `async`

    This PR adds support of async in magic-class.

    @magicclass
    class A:
        x = vfield(False)
        async def f(self):
            while not self.x:
                time.sleep(0.1)
            print("Checked")
    
    opened by hanjinliu 0
  • would like to remove `magicgui.signature`

    would like to remove `magicgui.signature`

    Hi @hanjinliu

    as part of https://github.com/pyapp-kit/magicgui/issues/474, I'd like to generally remove (or at least make private) everything inside of magicgui.signature (since I think functions were the wrong level to generally attack the type->widget mapping). but it looks like you're using MagicParameter quite a bit.

    Could you look into what it would take here to remove dependence on magicgui.signature? either by using other public functions from magicgui (such as directly using get_widget_type), or by vendoring whatever you want from magicgui.signature?

    thanks :)

    opened by tlambert03 2
  • Fix `singledispatchmethod` with options

    Fix `singledispatchmethod` with options "bind" or "choices"

    With currently implementation, @singledispatchmethod and @set_options with "bind" or "choices" method pointing at class methods are not compatible. ComboBox object is sent to self.

    opened by hanjinliu 0
  • Replace `macrokit` with `collections_undo`

    Replace `macrokit` with `collections_undo`

    collections-undo implements undo/redo to any functions. Although I have not implemented it yet, the recorded undo stack can also be utilized for macro generation.

    A big benefit of this replacement is that implementation of undo/redo in custom GUI will be much easier.

    enhancement 
    opened by hanjinliu 0
Releases(v0.6.13)
  • v0.6.13(Dec 9, 2022)

    New Features

    • Implement abstractapi. From now on, using abstractapi to pre-define methods is recommended.
      @magicclass
      class A:
          @magicclass
          class B:
              a = abstractapi()  # instead of def a(self): ...
          @B.wraps
          def a(self):
              # do something
      

      See here.

    • Implement with_progress method to thread_worker (#67). Changing code to use this is highly recommended.
      @thread_worker(progress={"desc": "running...", "total": 10})  # instead of this
      @thread_worker.with_progress(desc="running...", total=10)  # use this
      

      See here.

    • Implement wraps like field definition (#66).
    • Implement with_options and with_choices to magic fields. See here.
    • Add properties argument to @magicclass etc., to set min_width etc.
    • Syntax highlightening of macro widget (#65). Enable by defaults["macro-highlight"] = True.

    Changes

    • For upcoming magicgui==0.7, many imports of variables are refactored (#61).

    Bug Fixes

    • Bug fix in data orientation of vispy Points layer.
    • Title bar did not work in many popup mode (#62).
    • Fix widget visibility (#63).
    • Fix __getitem__ of widget macro and change the default macro history to 100k lines.
    • Fix vispy camera event emission bug for magicgui>=0.7.
    Source code(tar.gz)
    Source code(zip)
  • v0.6.12(Nov 3, 2022)

    New Features

    • Add matplotlib like API in magicclass.plot_api (#55).
    • Implement Points3D, Arrows3D layers and napari-style blending in magicclass.ext.vispy (#52, #56).
    • Implement impl_preview, a successor of mark_preview, for preview/prerun of method (#57).
    • Implement magicproperty for property like widget creation (#58).
    • Add magicclass.logging submodule for logging in a widget.

    Bug Fixes

    • Signals were not connected to FieldGroup (#51).
    • Child FunctionGui widgets were invisible (#54).
    • range objects were not formatted in macro.
    Source code(tar.gz)
    Source code(zip)
  • v0.6.11(Oct 27, 2022)

    New Features

    • Updates for magicgui=0.6.0.
    • magicclass.functools submodule for functools like functions.
      • partial ... partialize a function and its magicgui configuration
      • partialmethod ... partialize a method and its magicgui configuration.
      • singledispatchmethod ... call a method with a variable of different types.
    • New API in magicclass.ext.vispy submodule.
      • camera is now a HasFields subclass.
      • add_curve method.
    • Utility function call_recent_menu.
    • Union type in magicclass.types to create a widget tabbed with different widgets.

    Deprecations

    • The wraps function is moved to magicclass.functools submodule.
    Source code(tar.gz)
    Source code(zip)
  • v0.6.10(Sep 28, 2022)

    Improvements

    • Improved typing of @magicclass, @magicmenu, @magiccontext and @magictoolbar when they decorated a subclass of MagicTemplate.
    • Update titlebar design of docked magicgui widget.
    • Use container to store all the thread_worker progress bar.
    • Lazy import matplotlib in the file of Logger.

    Bug Fixes

    • Nested Annotated type did not work.
    • @wraps without pre-definition did not work correctly.

    New Widgets

    • HistoryLineEdit and HistoryFileEdit: widgets with value histories.
    Source code(tar.gz)
    Source code(zip)
  • v0.6.9(Aug 30, 2022)

    New Features

    • Add plot API to pyqtgraph extension subpackage.
    • Support PyQt6.

    Changes

    • Magicgui with configuration auto_call=True will not be called on reset_choices if it is invisible. This change is on the consideration of closed magicgui window in a napari viewer. Invisible auto calls should be disabled to avoid unexpected function call on layer deletion.

    Bug Fixes

    • dask_thread_worker did not create a new window correctly but used to update the old one.
    • The "Attributes" section of class doc of magicmenu was not parsed to the child fields.

    Deprecations

    • All the icon_path arguments/properties are removed. icon should be used now.
    Source code(tar.gz)
    Source code(zip)
  • v0.6.8(Aug 2, 2022)

    New Features

    • Install context menu to a push button using into argument of @magiccontext.
    • Many functions in vispy extension now works.
    • plot_api in vispy extension.
    • New popup mode "parentsub". In this mode, magicgui will be added to the parent as a subwindow.
    • dataclass_gui decorator for using HasFields and dataclass in combination.

    Bug Fixes

    • Make things compatible with older Qt.

    Deprecations

    • redo is renamed to repeat. redo will be removed in the future.
    Source code(tar.gz)
    Source code(zip)
  • v0.6.7(Jul 3, 2022)

    New Features

    • Add OneOf and SomeOf types for easier usage of ComboBox and Select. See documentation.
    • A Callback object for thread_worker using thread_worker.to_callback. See documentation.
    • Add supports of standard icons and converting np.ndarray into an icon. See documentation.
    • New helper function update_widget_state to update all the widget values using macro object.
    • Return annotation callback now works in magic-class and macro will be correctly recorded.

    Bug Fixes

    • Update __qualname__ on copying class to another.

    Deprecations

    • Tuple and List in magicclass.types are deprecated because they are now identical to typing.List and typing.Tuple.
    • icon_path keyword argument in @set_design is deprecated and icon keyword argument should be used instead because path is not the only type it accepts.
    Source code(tar.gz)
    Source code(zip)
  • v0.6.6(Jun 27, 2022)

    Bug Fixes

    • Set parent on launching dialog popup when popup_mode="dialog".
    • magicclass.ext.pyqtgraph widgets were not working in Mac due to difference in running QApplication.
    Source code(tar.gz)
    Source code(zip)
  • v0.6.5(Jun 22, 2022)

    New Features

    • New popup mode "dialog" is available. The Dialog widget of magicgui will be used.
    • str can now be used for "bind" and "choices" options. e.g. def func(self, x: Bound["_get_value"]) instead of def func(self, x: Bound[_get_value]).
    • Initial support of copy_info.
    • Choices type in magicclass.types: def func(self, x: Choices[1, 2, 3]) or def func(self, x: Choices[_get_choices]).
    • New napari type annotations in magicclass.ext.napari.types: Features, FeatureColumn, FeatureInfo. See examples.

    Deprecations

    • icon_size is deprecated. Icon size will be automatically determined by the button size.
    • click is moved from magicclass to magicclass.utils.

    Bug Fixes

    • confirm and thread_worker are now compatible.
    • Support magicgui>=0.5.0.
    • get_function_gui was not completely equivalent to clicking a button.
    Source code(tar.gz)
    Source code(zip)
  • v0.6.4(May 21, 2022)

    Highlights

    • Package design related to MagicField is significantly revised. Now fields can be used in many occasions. See documentation for more details.
      • field and vfield now can be used in any classes.
      • FieldGroup abstract class can be used to group fields.
      • HasFields trait is useful to define classes with fields.
      • pre_set_hook and post_get_hook.
    • If a class has "Attributes" block in its docstring, the contents will be parsed to field tooltips.

    New Features

    • Status tip property in main window GUI, via ui.status.
    • Use HasFields trait in vispy and vtk submodules.
    • SeabornFigure is available and works well.
    • Initial support of Table bound pandas data frame. Available in magicclass.ext.pandas

    Changes

    • MagicField no longer inherits dataclasses.Field

    Bug Fixes

    • Font error in Mac.
    • Missing dependency superqt.
    Source code(tar.gz)
    Source code(zip)
  • v0.6.3(May 4, 2022)

    Highlight

    • dask progress bar is available at magicclass.ext.dask. Wrap a method using dask_thread_worker and it can monitor da.compute.
    • field and vfield now work in combination with generic types, such as field(tuple[str, int]).
    • Use rich text in built-in error message box.

    Other New Features

    • Updates in magicclass.ext.vispy.
    • Scroll logger down when an image is appended.
    • Always update the timer of the default progress bar.
    • field()
    • Delete deprecations.

    Bug fixes

    • set_design made widgets visible.
    • thread_worker appended macro before end of exection.
    • Bug fix when using Optional and generic types in combination.
    • Bug fixes in help widget.
    Source code(tar.gz)
    Source code(zip)
  • v0.6.2(Apr 6, 2022)

    New Features

    • Updates in thread_worker.
      • The default progress bar created by thread_worker now has "pause" and "abort" button and displays time.
      • Clarify required methods for thread_worker progress bar using _SupportProgress protocol.
      • Add macro of calling thread_worker after it is finished.
    • @mark_preview decorator to define a preview function to widgets created by @magicgui. It works both in magic-class and in magicgui.
    • Now MagicTemplate has a custom meta-class. This update improves typing of nested magic-class. For instance, in the following definition
      @magicclass
      class A(MagicTemplate):
          @magicclass
          class B(MagicTemplate):
              def f(self): ...
          def g(self):
              self.B.f()
      

      the last line self.B.f() is not correct because native python type checker expects self.B.f(obj). This problem is fixed.

    • Initial support of SeabornFigure.

    Improvements

    • Do not create temporal FunctionGui widget when converting methods into push buttons or menus.
    • To show private child widgets as a floating dock widget in napari, it used to be docked on the right side before calling setFloating. To avoid it affecting existing dock widgets, it is changed to left side.

    Extensions

    • Experimental VTK support in magicclass.ext.vtk. Depend on vedo.
    • vispy 3D canvas supports add_surface. 2D canvas supports add_curve.

    Bug fixes

    • Minor error in logger widget right context menu.
    • Many private methods with key bindings did not get called.
    Source code(tar.gz)
    Source code(zip)
  • v0.6.1(Mar 25, 2022)

    Highlights

    • confirm decorator is working now. When a function is called from GUI, a dialog will be created to confirm whether it is OK to be run. Available at from magicclass import confirm.
    • The Figure widget is largely improved (#11). It is now interactive (currently linear-scale and log-scale are supported) and can be copied/saved via right click context menu.
    • Initial support of thread_worker for multi-threading (#14).

    New Features

    • The Logger widget now supports coping/saving inline images.
    • Labels and button visibility of ListEdit can now be controlled.
    • redo helper function. redo(self) repeats the last operation of self. Available at from magicclass import redo.

    Bug Fixes

    • Import bug fix in magicclass.ext.napari.
    • The "choices" option was broken if many GUI objects are constructed from the same magic class (#13).
    • The "enabled" option in field and vfield had no effect (#16).
    Source code(tar.gz)
    Source code(zip)
  • v0.6.0(Mar 12, 2022)

    New Features

    • Function call will be recorded in macro even if it is called programmatically. Accordingly, macro history is newly introduced to avoid recording too much.
    • Even if a sub magic class is defined outside the main magic class and used as a part of it, class will be copied and name space is correctly modified. Now you don't have to literally nest classes. Instead of
      @magicclass
      class Main:
          @magicclass
          class A:
              ...
      

      you can define them separately to keep codes clean.

      @magicclass
      class A:
          ...
      
      @magicclass
      class Main:
          A_widget = A
      
    • Logger widget is available in magicclass.widgets. This is a very powerful widget for outputs. You can stream print, logging outputs into the widget using context manager logger.set_stdout() and logger.set_logger(), or plt.plot in this widget just like inline plot using logger.set_plt().
    • Fields can be created if widget_type is specified.
    • Useful types in magicclass.types. If List, Tuple or Optional is imported from this submodule, these type annotations will be recognized by @magicgui and converted into ListEdit, TupleEdit and OptionalWidget respectively. These are temporary ones and may be replaced by magicgui in the future.
    • RangeSlider and FloatRangeSlider are available in magicclass.widgets. These are temporary ones and may be replaced by magicgui in the future.

    Bug fixes

    • Sub widgets were sometimes completely hidden if closed in napari.
    • If multiple viewers are created, macro did not work.

    Changes

    • __call__ will not be converted to widget because it is meaningless.
    • Macro recording of function calls.
    • Some types and variables such as Bound will be deleted from the main module. They should be imported from submodules from now on. DeprecationWarning is raised but will be error in the future.
    Source code(tar.gz)
    Source code(zip)
  • v0.5.22(Feb 28, 2022)

    New Features

    • xticks and yticks are available in Figure widget, just like plt.xticks and plt.yticks.
    • Initial support of vispy for mini-viewer. Available in magicclass.ext.vispy.

    Improvements

    • Inherit style sheet from toolbar to menu hidden in tool buttons.
    • Remove underscores in nested menus.
    • Warn on widget creation if set_options got parameters that do not exists in the wrapping function.
    • "choices" option did not work in some nested class.
    • Remove duplicated __magicclass_children__.
    • Now mypy can correctly resolve typing defined by Bound.
    • Ensure ui["x"] returns a widget (previously returns widget value if x is a MagicValueField).
    • Fix inconsistency in field names.
    Source code(tar.gz)
    Source code(zip)
  • v0.5.21(Feb 20, 2022)

    New Features

    • OptionalWidget is available for methods that have optional arguments with None as the default .
      from magicgui import magicgui
      from magicclass import Optional
      
      @magicgui
      def func(x: Optional[int] = None):
          print(x)
      

      Currently you have to import Optional type from magicclass but may also work with typing.Optional or int | None in the future.

    • The "choices" option in categorical widgets can be used with instance methods. See document for the detail.
    • enabled argument in field and vfield.

    Important Changes

    • The btn_text in containers are deprecated now in favor of text.
    • Bound(...) no longer works because the Bound type is a generic alias now. You should use Bound[...] instead.
    • Widget alignment of ScrollableContainer is changed to Qt.AlignTop.
    • Delete imports from magicgui.events. Now all the warnings of callbacks will raise errors.
    • The type_matching submodule is removed. Similar method may be implemented in magicgui.

    Bug Fixes

    • Use custom merge_super_sigs for correct module updates.
    • Some event emissions in ColorEdit and ColorSlider were broken.
    • MagicField did not work in Python 3.10 due to wrong tox settings.
    • Resolve QColor warnings.
    Source code(tar.gz)
    Source code(zip)
  • v0.5.20(Feb 4, 2022)

    New Features

    • New widgets SpreadSheet, ColorEdit, ColorSlider are available in magicclass.widgets.
    • "Show traceback" button in error message box.

    Bug Fixes

    • Ignore property in menu and toolbar.
    • Ignore classmethod.
    • Macro was not locked in callbacks of fields.
    • Make LiteralEvalLineEdit compatible with magic classes.
    • Text was not correctly set in widget actions.
    Source code(tar.gz)
    Source code(zip)
  • v0.5.19(Jan 26, 2022)

    Highlights

    • New method find_ancestor is available for any magic classes. ui.find_ancestor(X) will return an widget of X if it is a parent of ui. This will be an alternative way to get access to parents, instead of using @wraps.
    • At proper timing, macro recorders for napari types (Viewer and Layer types) will be loaded. They will be recorded like viewer.layers["name"] by default.
    • Class inheritance is supported in most cases. It safe to define methods, fields or nested classes in the base class and create multiple magic subclasses. See the document for details.

    New Features

    • find_ancestor method to search for parent widget.
    • The matplotlib's widget Figure in magicclass.widgets now has many methods similar to those used with plt. You can use such as widget.plot(...) (corresponds to plt.plot) and widget.xlim(...) (corresponds to plt.xlim) instead of widget.ax.plot() (correspond to ax.plot).
    • Load macro recorders for napari types.
    • @nogui decorator is available. Methods decorated with this will not be converted to widgets.
    • Initial support for stylesheet templates.
    • Add weak reference of parent widget to FunctionGuiPlus widgets.
    • Experimental support of add_dock_widget and remove_dock_widget methods for widget_type="mainwindow".
    • Avoid recording macro if function call ended with an exception.
    • New mode @magicclass(error_mode="stdout"). In this mode error will be printed.

    Improvements

    • Don't convert private methods into widgets (previously they were converted but not added).
    • Raise clearer error in FreeWidget if subclasses are not initialized correctly.
    • Support class inheritance.

    Bug Fixes

    • ListDataView was not recorded in macro correctly.
    • tqdm.ProgressBar was not updating.
    • Safely append functions after widget construction.
    • Callbacks of container variations was not called.
    • Macro recording of Enum was not correct in some cases.
    Source code(tar.gz)
    Source code(zip)
  • v0.5.18(Jan 19, 2022)

    New Features

    • collapsed property in collapsible containers. It enables expanding/collapsing widgets programmatically, by such as ui.collapsed = True.
    • When a magic class has multiple classes decorated with @magictoolbar, then toolbars will be tabified.
    • You can change the initial visibility of a widget by option @magicclass(visible=False).
    • FrameContainer is available, which is similar to GroupBoxContainer but does not have title on its top. Available via @magicclass(widget_type="frame").
    • Make copies of method using wraps decorator, using keyword argument @wraps(copy=True) or without it if multiple @wraps decorate the same method.
    • "Execute selected lines" action in macro widget.
    • magicclass.tqdm extends tqdm usage in magicgui.tqdm, which makes ProgressBar more useful in magic classes.
    • New option set_options(labels=False) similar to magicgui(labels=False).
    • @confirm decorator is added (experimentally though). Method decorated with @confirm("xxx") will open a GUI that confirms whether it's OK to run function.

    Bug Fixes and Improvements

    • Adding menu bar and/or toolbar to certain type of containers did not work. Now works with any widgets. This bug fix includes improvement in containers that have scroll area. Menu bar and toolbar will be added outside the scroll area so that they are always visible.
    • Many improvements in type annotation of field and vfield.
    • core.pyi was not installed.
    • Many fixes in type annotation of magicclass and other relevant functions.
    • GUI took very long time to show up when napari is installed because the contents of napari happened to be imported in show() method.
    • Use object.__setattr__ instead of setattr to make widget construction a little bit faster.
    • The current_index property of tabbed container was broken.
    • Remove matplotlib dependency.
    Source code(tar.gz)
    Source code(zip)
  • v0.5.17(Jan 13, 2022)

    This release fixed an important bug in v0.5.16.

    Bug Fixes

    • NameError when optional packages are not installed.
    • labels=False option in menu bar and toolbar took no effect.

    Changes

    • All the extended widgets such as QtConsole and QtPlotCanvas are moved to magicclss.ext submodule. They are no longer available in magicclass.widgets.

    Improvements

    • Better typing in MagicField. For instance, if you have a field f = field(SpinBox) then type checker knows that f will be a SpinBox when accessed via GUI instance.
    • Containers with scroll area (magicclass options widget_type="scrollable" or widget_type="draggable") will assign menu bar and tool bar outside their scroll area so that menu bar and tool bar are always visible.
    Source code(tar.gz)
    Source code(zip)
  • v0.5.16(Jan 9, 2022)

    New Features

    • New methods add_text, add_infline in pyqtgraph based widgets.
    • Initial support for pyvista (WIP). Available in magicclass.widgets
    • Both menu and toolbar can be defined in non-main window.
    • set_options can take auto_call, call_button, layout arguments.

    Bug Fixes

    • MagicField callback bug fix.
    • Toolbar updates its style sheet when added to napari viewer.
    • Update FunctionGui categorical widgets hidden in buttons and actions.
    Source code(tar.gz)
    Source code(zip)
  • v0.5.15(Jan 3, 2022)

    New Features

    • Many updates in pyqtgraph based widgets.
      • QtPlotCanvas supports histogram and bar plot. It also has a linear region item in canvas.region by default.
      • QtImageCanvas has scale bar by default. The LUT histogram is hidden by the button on the upper-left corner now.
      • Much more unified API between line plot item, scatter plot item and others, such as face_color, edge_color and symbol.
      • QtMultiPlotCanvas, QtMultiImageCanvas can contain multiple plots and images in a single widget.
      • Qt2YPlotCanvas has two Y-axis and shared X-axis.
    • to_napari function is available in magicclass.ext submodule. Any magic classes, no matter it is a widget or a menu, can directly docked into napari viewer by simple syntax:
      from magicclass.ext import to_napari
      @to_napari
      @magicclass
      class A: ...
      
    • Now functions can be converted into buttons or menus after construction of magic classes. This also follows the magicgui's typing rule.
      def func(a: int): ...
      ui.Menu.append(func)  # this code will create a new action in Menu.
      

    Changes

    • parent_viewer finds viewer ancestor in a safer way now. It uses napari's method so that it will also work with newer napari in the future.
    • Use pyi file to improve code completion.
    Source code(tar.gz)
    Source code(zip)
  • v0.5.14(Dec 17, 2021)

    New Features

    • magictoolbar creates a ToolBarGui, which appears as a tool bar on the top of a widget. It is inter-nestable with magicmenu.
    • Horizontal collapsible container using widget_type="hcollapsible".
    • Automatically determine how to execute QApplication. In the previous versions you had to add such as input() to prevent application exiting immediately if you ran a ".py" file with python command. Now you don't have to do that.
    • Icon supports in many widgets.
    • icon_path is now a universal option for widgets and fields. It can be used as @magicclass(icon_path="..."), field(int, options={"icon_path": "..."}).
    • ConsoleTextEdit has new property tab_size, with which you can set the size of tab.

    Bug Fixes

    • Checkable actions in menus were not working.
    • wraps was not working when a magic class was defined locally.

    Others

    • Added many tests.
    • Remove matplotlib dependency.
    Source code(tar.gz)
    Source code(zip)
  • v0.5.13(Dec 12, 2021)

    Bug Fixes

    • Fix annotations for Python 3.8.
    • wraps and FunctionGui was not compatible.
    • Some popup modes was not correctly working.
    • Fix typo of "draggable".
    Source code(tar.gz)
    Source code(zip)
  • v0.5.12(Dec 11, 2021)

    New Features

    • Built-in macro widget is working! Get executable scripts by str(ui.macro), or show the widget by ui.macro.widget.show(). This widget is already equipped with many functions, such as "create macro" or "run macro".
    • Help widget is working! Use build_help to make illustrated documentation automatically.
    • datetime objects are correctly recorded in macro. With macro-kit>=0.3.3, the datetime module is automatically passed to eval function so that macro can be executed safely.
    • Menu bar objects support rendering similar to Widget.
    • New container variation DraggableContainer is available. Instead of scrolling using scroll bar, this container supports scrolling by mouse drag. Create by @magicclass(widget_type="draggable").

    Changes

    • The create_macro method will cause deprecation warning. It will be removed soon. Use ui.macro instead.
    • Delayed matplotlib import.

    Bug Fixes

    • MagicValueField was not compatible with latest macro recording system.
    Source code(tar.gz)
    Source code(zip)
  • v0.5.11(Dec 5, 2021)

    New Features

    • bind_key can bind private methods to keyboard shortcuts now.
    • MagicTemplate can check undesired override when subclassed.

    Changes

    • Macro recording functions are now dependent on macro-kit.
    • Try/except block in method-to-widget conversion, because some callable objects is not compatible with magic class construction.
    • The myname="ui" argument in create_macro method is deleted because this change can simplify the code a lot.
    • Block macro recording if it is caused by another function that causes macro recording.

    Bug Fixes

    • Tooltips was disabled by magic-class wraps methods (docstrings were not inherited correctly).
    • Magic classes inserted into parent magic class did not update __magicclass_parent__ attribute.
    • Bug fix in container generated by widget_type="list".
    Source code(tar.gz)
    Source code(zip)
  • v0.5.10(Dec 1, 2021)

    New Features

    • Custom key-binding is working! Decorate method with @bind_key("Ctrl-A") and that's it.
    • New container GroupBoxContainer with option magicclass(widget_type="groupbox")
    • to_clipboard helper function.

    Changes

    • show_messagebox are moved to magicclass.utils
    Source code(tar.gz)
    Source code(zip)
  • v0.5.9(Nov 25, 2021)

    New Features

    • Add traceback of widget creation history and error causing method definition when magic class construction failed.
    • DictWidget similar to ListWidget is available.
    • ProgressWidget is partly working in parallel.
    • show_url function for opening a URL in the default web browser.
    • Any widgets can now be added to menu bar via QWidgetAction.
    • NapariCanvas is available now, which is useful for building simple napari-like widget.
    • MagicTemplate is available, which is useful to make magic class specific attributes discoverable from IDE and console.
    • New container variation based on QMdiArea (widget_type="subwindows").

    Changes

    • wraps system was completely re-implemented. Now it actually calls parent method. No API changes.
    • magicclass in magicmenu will actually be docked into the menu bar for integrity of API.

    Bug Fix

    • Compatibility of Bound and fields.
    • Make QtConsole compatible to current implementation.
    Source code(tar.gz)
    Source code(zip)
  • v0.5.8(Nov 21, 2021)

    New Features

    • All the push buttons have running attribute now. This attribute is True only when the function is running in magicgui side, that is, executed from GUI. It is useful when a function need to know how it is called (e.g. don't use thread worker when function is called from script).
    • MagicValueField and vfield can make a field that is more similar to Python property. See the document for details.
    • record option in field function. Use field(..., record=False) to avoid recording value changes in macro.
    • "bind" option supports MagicField now. See the document for details.
    • Bound function for annotation with "bind" options.
    • Traceback of widget creation will be printed when an error occurred during magic-class construction.

    Important Changes

    • MagicField is now always referred via __get__. There is not change in API, but fields became immutable.
    • FrozenContainer is no longer used because it doesn't have to be a container. FreeWidget is now used instead. Therefore, Containter's methods are no longer supported.
    • Many methods of ListWidget are renamed because it is no longer a Container. It is much more similar to Python list now.
      • add_itemappend
      • insert_iteminsert
      • pop_itempop

    Bug fixes

    • The disgusting spaces in separators are removed.
    • Annotated type works well in magic-class.
    Source code(tar.gz)
    Source code(zip)
  • v0.5.7(Nov 15, 2021)

    Changes

    • QtPlotCanvas.layers and QtImageCanvas.layers now return LayerList object, which acts much more similar to napari's layer list.
    • show_messagebox function for popping up a message box dialog.

    Bug Fixes

    • error_mode="stderr" bug fix.
    • The image layer of QtImageCanvas was off by 0.5 pixel compared to napari and matplotlib.
    Source code(tar.gz)
    Source code(zip)
Owner
Department of Biological Sciences, School of Science, The University of Tokyo. My major is biophysics, especially microtubule and motor proteins.
null
guietta - a tool for making simple Python GUIs

guietta - a tool for making simple Python GUIs

Alfio Puglisi 1.9k Jan 8, 2023
build GUIs from python functions, using magic.

magicgui: build GUIs from functions, using magic. ?? Docs Installation magicgui uses qtpy to support both pyside2 and pyqt5 backends. However, you mus

napari 0 Nov 11, 2022
Tkinter Designer - Create Beautiful Tkinter GUIs by Drag and Drop.

Tkinter Designer is created to speed up and beautify Python GUI Experience. It uses well know design software called Figma. Which makes creating Tkinter GUI in Python a piece of cake.

Parth Jadhav 5.2k Jan 9, 2023
guietta - a tool for making simple Python GUIs

guietta - a tool for making simple Python GUIs

Alfio Puglisi 1.9k Jan 8, 2023
build GUIs from python functions, using magic.

magicgui: build GUIs from functions, using magic. ?? Docs Installation magicgui uses qtpy to support both pyside2 and pyqt5 backends. However, you mus

napari 0 Nov 11, 2022
Multifunctional library for creating progress bars.

?? Content Installation Using github Using pypi Quickstart Flags Useful links Documentation Pypi Changelog TODO Contributing FAQ Bar structure ⚙️ Inst

DenyS 27 Jan 1, 2023
Mikasa is a 100% Spanish bot, a multifunctional bot, Mikasa is in beta.

Mikasa Miaksa, It is a multi-functional discord bot that is currently in development, this is not complete, there are still many things to fix and imp

Made in 2 Oct 5, 2021
Multifunctional Analysis of Regions through Input-Output

MARIO Multifunctional Analysis of Regions through Input-Output. (Documents) What is it MARIO is a python package for handling input-output tables and

null 14 Dec 25, 2022
A multifunctional bot for Discord

Um bot multifuncional e divertido para Discord Estive desenvolvendo o BotDaora desde o começo de outubro de 2021 e agora ele é open-source! tomei essa

Ruan 4 Dec 28, 2021
A program that takes Python classes and turns them into CSS classes.

PyCSS What is it? PyCSS is a micro-framework to speed up the process of writing bulk CSS classes. How does it do it? With Python!!! First download the

T.R Batt 0 Aug 3, 2021
Python Bot that attends classes, answers polls, and then again waits for classes to start.

LPU_myclass_Bot LPU_myclass_Bot is a Python bot that waits for class to start, attends class, answers polls, and then again waits for another class to

Saurabh Kumar 6 Apr 7, 2022
A simple python script to generate an iCalendar file for the university classes.

iCal Generator This is a simple python script to generate an iCalendar file for the university classes. Installation Clone the repository git clone ht

Foad Rashidi 2 Sep 1, 2022
theHasher Tool created for generate strong and unbreakable passwords by using Hash Functions.Generate Hashes and store them in txt files.Use the txt files as lists to execute Brute Force Attacks!

$theHasher theHasher is a Tool for generating hashes using some of the most Famous Hashes Functions ever created. You can save your hashes to correspo

SR18 6 Feb 2, 2022
Inspects Python source files and provides information about type and location of classes, methods etc

prospector About Prospector is a tool to analyse Python code and output information about errors, potential problems, convention violations and comple

Python Code Quality Authority 1.7k Dec 31, 2022
A toolbelt of useful classes and functions to be used with python-requests

The Requests Toolbelt This is just a collection of utilities for python-requests, but don't really belong in requests proper. The minimum tested reque

null 892 Jan 6, 2023
Tweak the form field rendering in templates, not in python-level form definitions. CSS classes and HTML attributes can be altered.

django-widget-tweaks Tweak the form field rendering in templates, not in python-level form definitions. Altering CSS classes and HTML attributes is su

Jazzband 1.8k Jan 2, 2023
Inspects Python source files and provides information about type and location of classes, methods etc

prospector About Prospector is a tool to analyse Python code and output information about errors, potential problems, convention violations and comple

Python Code Quality Authority 1.7k Dec 31, 2022
Macros in Python: quasiquotes, case classes, LINQ and more!

MacroPy3 1.1.0b2 MacroPy is an implementation of Syntactic Macros in the Python Programming Language. MacroPy provides a mechanism for user-defined fu

Li Haoyi 3.2k Jan 6, 2023
Python Classes Without Boilerplate

attrs is the Python package that will bring back the joy of writing classes by relieving you from the drudgery of implementing object protocols (aka d

The attrs Cabal 4.6k Jan 2, 2023