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.