Callable widget example is broken or maybe the widget
Example code: https://pyapp-kit.github.io/magicgui/generated_examples/applications/callable/
Version on macports: py313-magicgui @0.10.0 (python)
Problem: Shows double run buttons.
When I write my own example with default set to None, it shows the "run" button initially, but it disappears if I select "f" then None. A better behaviour would be for the run button to be disabled on None or remove it initially.
My testcode:
from magicgui import magicgui
def f(x:int, y:str) -> str:
return f"f({x},{y})"
def g(x:int, y:int) -> str:
return f"g({x},{y})"
@magicgui(call_button=True, func={"choices": ["f", "g"]})
def example(func=None):
pass
def update(name: str):
if len(example) > 1:
del example[1]
if name is not None:
example.insert(1, magicgui(globals()[name]))
def main():
example.func.changed.connect(update)
example.show(run=True)
if __name__ == '__main__':
main()
I agree, that example is a little wonky...
Honestly, (in retrospect) I think it's a convoluted usage of the @magicgui call there just to make a container that isn't really, itself a function. I think i would probably write it more like this now (this includes your enable/disable run button behavior)
from magicgui import magicgui, widgets
def f(x: int, y: str = "a string") -> None:
"""Example function F."""
print(f"f({x}, {y})")
def g(x: int = 6, y: str = "another string") -> None:
"""Example function G."""
print(f"g({x}, {y})")
combo = widgets.ComboBox(name="func", choices=["f", "g"], nullable=True)
run = widgets.Button(text="Run")
run.enabled = False
example = widgets.Container(widgets=[combo, run])
@run.clicked.connect
def run_func() -> None:
"""Run the selected function."""
func_widget = example[1]
if callable(func_widget):
func_widget()
@combo.changed.connect
def update(func_name: str | None) -> None:
"""Update function."""
if func_name is None:
run.enabled = False
if len(example) > 2:
del example[1]
else:
run.enabled = True
func = globals()[func_name]
example.insert(1, magicgui(func, call_button=False))
example.show(run=True)
if you were more interested in the concept of a callable that is itself dynamic, let me know... but if you're more interested in a dynamic UI/widget that has a (stable) underlying callable behavior, that's how I'd do it