# Add toggle hotkey to custom checkbox

I have a self made checkbox in a script. Now I want to create a hotkey in the Input manager to toggle it.

What I have done so far is to create a keymap item with wm.context_toggle. But I cannot get the Context Attribute to work. I grab the one from my script, the Python term in the tooltip. Which is WindowManager.deselect_bool and with that I get an error that the "Object has no attribute WindowManager".

What is the proper Context Attribute term here? Is it even possible to do it this way? If not, what is the proper way to assign a toggle hotkey for my custom checkbox?

Script:

import bpy
from bpy.props import BoolProperty

class LayoutDemoPanel(bpy.types.Panel):
bl_label = "Demo Panel"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'

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

wm = context.window_manager # Our bool is in the windows_manager
layout.prop(wm, "deselect_bool") # Our checkbox

def register():
bpy.types.WindowManager.deselect_bool = bpy.props.BoolProperty(
name="Checkbox", description="A checkbox", default = False)
bpy.utils.register_module(__name__)

def unregister():
del bpy.types.WindowManager.deselect_bool # Unregister our flag when unregister.
bpy.utils.unregister_module(__name__)

if __name__ == "__main__":
register()


• The context attribute would be window_ manager.deselect_bool WindowManager is the class of context.window_manager Look in system console for error messages. – batFINGER Jul 23 '16 at 16:48
• @batFINGER, thanks, but i get just another error message now, SyntaxError: invalid syntax. And no hint where. location: :-1 – Tiles Jul 23 '16 at 17:14
• batFINGERs suggestion works for me when using your script, are you sure you don't have a typo somewhere? One thing that's strange however: The hotkey does work, but the checkbox is updated only if you put the mouse cursor into the panel where it lives in. Not sure if that really is the way to go – aliasguru Jul 23 '16 at 18:42
• That's odd. I have copied and pasted the terms to avoid typoes. And as told, i get the upper error when i have the mouse over the 3D view. But thanks for your observation. When i have the mouse over the panel then i don't get the error message. But the checkbox doesn't toggle neither, which it does for you. What do we overlook here? – Tiles Jul 23 '16 at 18:59
• Ah, wasn't a good idea to copy the term from batFINGER's post. He had a gap in window_ manager. When i write window_manager then the error is gone. But still no toggle with the hotkey :( – Tiles Jul 23 '16 at 19:02

Here is an example based on this answer. Once it's registered you can press ShiftQ to toggle your BoolProperty. Also notice that tagging the area for a redraw via context.area.tag_redraw() is requiered after the assignment call in oder to update the Panel properly:

Once it's enabled (or registered) the shortcut is created automatically:

custom-toggle-shortcut.py

bl_info = {
"description": "",
"author": "poor",
"version": (0, 0, 1),
"blender": (2, 70, 0),
"location": "3D View > Tools",
"warning": "", # used for warning icon and text in addons panel
"wiki_url": "",
"tracker_url": "",
"category": "Development"
}

import bpy

# ------------------------------------------------------------------------
#    my properties
# ------------------------------------------------------------------------

class MySettings(bpy.types.PropertyGroup):

my_bool = bpy.props.BoolProperty(
name="Enable or Disable",
description="A bool property",
default = False
)

# ------------------------------------------------------------------------
#    operators
# ------------------------------------------------------------------------

class ToggleOperator(bpy.types.Operator):
bl_idname = "view3d.toggle_mybool"
bl_label = "Toggle My Bool"
bl_options = {'REGISTER', 'UNDO'}

def execute(self, context):
context.scene.my_tool.my_bool = not context.scene.my_tool.my_bool
context.area.tag_redraw()
return {'FINISHED'}

# ------------------------------------------------------------------------
#    my tool in objectmode
# ------------------------------------------------------------------------

class OBJECT_PT_my_panel(bpy.types.Panel):
bl_idname = "OBJECT_PT_my_panel"
bl_label = "My Panel"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_context = "objectmode"

@classmethod
def poll(self,context):
return context.object is not None

def draw(self, context):
layout = self.layout
scene = context.scene
mytool = scene.my_tool
layout.prop(mytool, "my_bool")

# ------------------------------------------------------------------------
#     register and unregister
# ------------------------------------------------------------------------

def register():
bpy.utils.register_module(__name__)
bpy.types.Scene.my_tool = bpy.props.PointerProperty(type=MySettings)

# handle the keymap
wm = bpy.context.window_manager
if kc:
kmi = km.keymap_items.new(ToggleOperator.bl_idname, type='Q', value='PRESS', shift=True)

def unregister():

km.keymap_items.remove(kmi)

bpy.utils.unregister_module(__name__)
del bpy.types.Scene.my_tool

if __name__ == "__main__":
register()


Alternatively using an update method

Rather than create a new operator use the wm.context_toggle operator, and set up an update method on the property that will redraw the area when run. If the panel is in same area as key press then would only need update=prop_update

def prop_update(self, context):
context.area.tag_redraw()
return None


In example below area_ui_update('VIEW_3D') returns an update method where if area.type == 'VIEW_3D' in screen.areas that area will redraw. Useful when your panel is in an area other than context.area eg if your panel was in 'PROPERTIES' you would area_ui_update('PROPERTIES')

import bpy

def area_ui_update(type):
''' tag redraw on areas of type '''
def ui_update(self, context):
areas = [a for a in screen.areas if a.type == type]
for a in areas:
area.tag_redraw()
return None
return ui_update

class MySettings(bpy.types.PropertyGroup):

my_bool = bpy.props.BoolProperty(
name="Enable or Disable",
description="A bool property",
default = False,
update=area_ui_update('VIEW_3D')
)

# ------------------------------------------------------------------------
#    my tool in objectmode
# ------------------------------------------------------------------------

class OBJECT_PT_my_panel(bpy.types.Panel):
bl_idname = "OBJECT_PT_my_panel"
bl_label = "My Panel"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_context = "objectmode"

@classmethod
def poll(self,context):
return context.object is not None

def draw(self, context):
layout = self.layout
scene = context.scene
mytool = scene.my_tool

layout.prop(mytool, "my_bool")

# ------------------------------------------------------------------------
# register and unregister
# ------------------------------------------------------------------------

# register
def register():
bpy.utils.register_module(__name__)
bpy.types.Scene.my_tool = bpy.props.PointerProperty(type=MySettings)

# handle the keymap
wm = bpy.context.window_manager
if kc:
kmi = km.keymap_items.new("wm.context_toggle", type='Q', value='PRESS', shift=True)
kmi.properties.data_path = "scene.my_tool.my_bool"

# unregister
def unregister():

km.keymap_items.remove(kmi)

bpy.utils.unregister_module(__name__)
del bpy.types.Scene.my_tool

if __name__ == "__main__":
register()

• Hope you like new addition. – batFINGER Jul 25 '16 at 7:53
• Very much. I'm still at investigating. Thank you both :) – Tiles Jul 25 '16 at 8:16
• One small problem is left. The Info editor does not display the changes to the bool. That happens just when you click the checkbox. Any ideas here? :) – Tiles Jul 26 '16 at 8:42
• @Tiles That's normal behavior. Reflecting a bool change in the info area, only works when clicking a property or calling an operator. You can test this by your own - assign a shortcut to a existent bool property and you'll see that nothing shows up. Again, for simplicity I suggest use my Add-on template. You will see that the operator call shows up in the info area. Alternatively you can report any change in the info area, I updated the gist: gist.github.com/p2or/8a37617c4565e4ff143b736a0e4a1660, see line 43 and 46. More info here: blender.stackexchange.com/q/717/3710 – p2or Jul 26 '16 at 10:34
• Perfect. Now we have really everything :) – Tiles Jul 26 '16 at 10:56

The answer from batFINGER was the solution for the intial problem:

The context attribute would be window_manager.deselect_bool WindowManager is the class of context.window_manager Look in system console for error messages. – batFINGER