How can I make a dialog window make changes in real time?

Watching a tutorial from youtube I managed to setup an addon with a tab into VIEW_3D > UI, which contains a panel with some buttons (operators) where if you press any of them, you get a different dialog window with some properties, labels etc.


What I want to do is to have the ability to see changes in real time and not when I press OK. Something like this…


Is that possible? And if yes, how can I do that? Because I tried to execute my action through draw method but I get this error AttributeError: Writing to ID classes in this context is not allowed: Scene, Scene datablock, error setting LayerCollection.hide_viewport.

Here is an example of my code…

class fu3dm_WM_OT_Model_Prefs_Operator(bpy.types.Operator):
    bl_idname = "wm.fu3dm_model_prefs"
    bl_label = "Model Preferences"
    bl_description = "Blah blah blah"

    fu3dm_model_gender : bpy.props.EnumProperty(name="Gender", description="Choose model's gender", items= [('OP1', "Male", ""), ('OP2', "Female", "")], default='OP1')
    fu3dm_model_head_male : bpy.props.EnumProperty(name="Head", description="Choose model's head", items= [('OP1', "Generic Male", ""), ('OP2', "Christiano Ronaldo", "")], default='OP2')
    fu3dm_model_head_female : bpy.props.EnumProperty(name="Head", description="Choose model's head", items= [('OP1', "Generic Female", ""), ('OP2', "Ashlyn Harris", "")], default='OP2')
    fu3dm_model_eyes_color : bpy.props.IntProperty(name="Eyes Color", description="Choose model's eyes color", min=1, max=10, default=1)
    fu3dm_model_skin_color: bpy.props.IntProperty(name="Skin Color", description="Choose model's skin color", min=1, max=10, default=1)
    fu3dm_model_upper_body : bpy.props.EnumProperty(name="Upper Body", description="Choose model's upper body mesh", items= [('OP1', "Arms for Long Sleeves", ""), ('OP2', "Arms for Short Sleeves", ""), ('OP3', "Full Upper Body", "")], default='OP2')
    fu3dm_model_lower_body : bpy.props.EnumProperty(name="Lower Body", description="Choose model's lower body mesh", items= [('OP1', "Legs without Socks", ""), ('OP2', "Legs with Low Socks", ""), ('OP3', "Legs with Short Socks", ""), ('OP4', "Legs with Medium Socks", ""), ('OP5', "Legs with Long Socks", ""), ('OP6', "Legs with Medium Socks but without Shinpads", ""), ('OP7', "Full Lower Body", "")], default='OP4')
    def invoke(self, context, event):
        return context.window_manager.invoke_props_dialog(self)
    def draw(self, context):    
        layout = self.layout    
        box =
        col = box.column()

        row = col.split()
        row.prop(self, "fu3dm_model_gender", text="")

        if self.fu3dm_model_gender == 'OP1':
            row = col.split()
            row.prop(self, "fu3dm_model_head_male", text="")
            self.do_it(self=self, context=context)
            row = col.split()
            row.prop(self, "fu3dm_model_head_female", text="")
            self.do_it(self=self, context=context)

        row = col.split()
        row.label(text="Eyes Color:")
        row.prop(self, "fu3dm_model_eyes_color", text="")

        row = col.split()
        row.label(text="Skin Color:")
        row.prop(self, "fu3dm_model_skin_color", text="")

        row = col.split()
        row.label(text="Upper Body:")
        row.prop(self, "fu3dm_model_upper_body", text="")

        row = col.split()
        row.label(text="Lower Body:")
        row.prop(self, "fu3dm_model_lower_body", text="")

    def execute(self, context):
        return {"FINISHED"}

    def do_it(self, context):
        vlayer = bpy.context.scene.view_layers['View Layer']
        if self.fu3dm_model_gender == 'OP1':
            vlayer.layer_collection.children['MALE'].hide_viewport = False
            vlayer.layer_collection.children['FEMALE'].hide_viewport = True
            vlayer.layer_collection.children['MALE'].hide_viewport = True
            vlayer.layer_collection.children['FEMALE'].hide_viewport = False

Please keep in mind that I am totally new to blender and python!!!

You can use property setters or getters so in this way you can update some function each time the value is read.

However be cautious not to read the same property from within the getter and run into infinite loop. :slight_smile: If ever happens this you can use an intermediate property instead so it doesn’t form a chain of calls.