Use magicproperty in magic-class
In magicclass
, properties will not be conveted into widgets. The reason for this is
that properties are usually used to get references to one of the child widgets.
from magicclass import magicclass, field
@magicclass
class A:
@magicclass
class B:
x = field(int)
@property
def bx(self):
return self.B.x
However, another property-like class magicproperty
is available to build
a FunctionGui
-like widget.
Note
magicproperty
is a subclass of MagicField
.
How to Use magicproperty
Basically, it is used exactly the same as the built-in property
class, except that you
have to provide at least one type annotation for widget creation.
from magicclass import magicclass, magicproperty
@magicclass
class A:
@magicproperty
def x(self) -> int:
return self._x
@x.setter
def x(self, val: int):
self._x = val
@magicproperty
def string(self) -> str:
return self._s
@string.setter
def string(self, val: str):
self._s = val
ui = A()
ui.show()
Values are updated after the "Set" button is clicked, or set programmatically.
ui.x = 10 # update the value and the GUI
ui.string = "Hello" # update the value and the GUI
Configuration of magicproperty
magicproperty
can be configured similar to magicgui
. Here's some examples of how to
configure.
@magicclass
class A:
# set widget label
@magicproperty(label="X")
def x(self) -> int:
...
# widget type and options
@magicproperty(widget_type="Slider", options={"min": 0, "max": 10})
def x(self) -> int:
...
# auto-calling
@magicproperty(auto_call=True)
def x(self) -> int:
...
# customize the button text
@magicproperty(call_button="update x value")
def x(self) -> int:
...
Setter-only property
Although it's rare, built-in property
can be setter-only. In this case, you
can only set a value and getting a value is forbidden.
class A:
x = property()
@x.setter
def x(self, val):
print("set x to", val)
# python >= 3.9
@property().setter
def x(self, val):
print("set x to", val)
a = A()
a.x = 10 # OK
a.x # AttributeError
Unlike property
, however, the getter of magicproperty
doesn't need to be
defined because widget itself has its own value.
@magicclass
class A:
x = magicproperty(widget_type="Slider")
@x.setter
def x(self, val: int):
print("set x to", val)
# python >= 3.9
@magicproperty(widget_type="Slider").setter
def x(self, val: int):
print("set x to", val)
a = A()
a.x = 10 # OK
a.x # Out: 10
An advantage of setter-only magicproperty
is that you don't have to prepare
an additional attribute _x
for the property x
.
Note
You can even create a magicproperty
without any descriptors.
@magicclass
class A:
x = magicproperty(annotation=int)
y = magicproperty(widget_type="RangeEdit")
In this case, getter will get the value of the widget and setter will update the widget value.