1
$\begingroup$

How do you toggle an operator? A prop works

row.prop(bpy.context.object, 'lock_rotation', text = "", icon = "UNLOCKED", toggle = True)

but using an operator does not:

row.operator('object.idname', text = "", icon = "EVENT_O", toggle = True)

I get this error when "toggle = True" is added to an Operator:

TypeError: UILayout.operator(): was called with invalid keyword argument(s) (toggle), expected (operator, text, text_ctxt, translate, icon, emboss, depress, icon_value)
$\endgroup$

1 Answer 1

2
$\begingroup$

In this case it's a layout display option.

The toggle option for

UILayout.prop

toggle (int in [-1, 1], (optional)) – Use toggle widget for boolean values, or a checkbox when disabled (the default is -1 which uses toggle only when an icon is displayed)

layout.prop(context.object, "some_bool_prop", toggle=True)

is to make the boolean property appear like a button in the UI, rather than a checkbox. Please note that context is always passed to a draw method, so there is never a need to see bpy.context

To do the same with an operator, there is the bpy.ops.wm.context_toggle() operator, (Seen often in the keymaps)

op = layout.operator("wm.context_toggle")
op.data_path = "object.some_bool_prop"

where the data path is relative to context.

An operator is displayed as an embossed button by default in the UI, setting

op = layout.operator("wm.context_toggle", emboss=False)

will make it more link like.

BoolVectorProperty

The lock_rotation is a vector property with a boolean for each axis.

enter image description here

Example setting only the X axis (index = 0) lock. New draw method for Text Editor > Templates > Pythons > UI Panel Simple The panel only polls if there is a context object. This ensures that the object is the one that has the properties being displayed. Not doing so will result in an error, generally notable by seeing 'NoneorNoneType` in the error message

Hide Panel With Python

    def draw(self, context):
        layout = self.layout

        obj = context.object

        row = layout.row()
        row.prop(obj, "lock_rotation", index=0, toggle=False)
        row.prop(obj, "lock_rotation", index=0, toggle=True)

        op = row.operator("wm.context_toggle")
        op.data_path = "object.lock_rotation[0]"
        op = row.operator("wm.context_toggle", emboss=False)
        op.data_path = "object.lock_rotation[0]"
$\endgroup$
3
  • $\begingroup$ Thanks! The reason I was trying to use an Operator (row.operator) rather than Prop is because I was trying to setup an Execute function in the Operator to offer more control, and because row.prop(obj, "lock_rotation", index=0, toggle=True) throws a ...'None" assignment AnyType type error when an object is deleted in the scene. I seem to be stuck between either having the error but with a working toggle, or getting rid of the error but not having toggle functionality. Still trying to wrap my head around it $\endgroup$
    – Increality
    Feb 17, 2021 at 4:21
  • 1
    $\begingroup$ Sounds to me like you have a poll issue... recently answered blender.stackexchange.com/questions/212075/… Make sure your panel doesn't poll when context.object is None other wise None.lock_rotation is going to give errors, when ... say ... you remove... $\endgroup$
    – batFINGER
    Feb 17, 2021 at 4:24
  • $\begingroup$ Genius! That did it, thanks $\endgroup$
    – Increality
    Feb 17, 2021 at 4:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .