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$
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 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 at 4:24
  • $\begingroup$ Genius! That did it, thanks $\endgroup$
    – Increality
    Feb 17 at 4:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.