I'm trying to add a callback which runs at every SpaceView3D draw. As suggested from Change Current Frame acc. to Active Layer.

class DrawClass:
    def __init__(self, context):
       self.handle = bpy.types.SpaceView3D.draw_handler_add(self.draw_callback, (context,), 'WINDOW', 'POST_PIXEL')

    def draw_callback(self):

if __name__ == "__main__":

This is a script I wrote to test if my callback function gets added to the draw handler. I would expect an output from print function on the console I started Blender from. But I get nothing. Am I doing something wrong here?

  • $\begingroup$ Yes you are. In the handle adding in code in link posted (context,) is the argument(s) being passed to the callback method. You have defined the method with no other arguments def draw_callback(self) it's one or the other, pass no arguments or declare them in method defn. $\endgroup$
    – batFINGER
    Commented Dec 24, 2019 at 11:16
  • $\begingroup$ @batFINGER I understand. I changed the arguments specified to () which I assume is the right syntax for no arguments in python. But the code still doesn't produce any output from the print function. $\endgroup$
    – user56873
    Commented Dec 24, 2019 at 11:43
  • $\begingroup$ You might need to call context.area.tag_redraw() to update every frame. $\endgroup$ Commented Mar 14, 2021 at 22:33

1 Answer 1


All possible callbacks

enter image description here Prints to console when callbacks fired

So much info in the python console, autocomplete on draw handler add. Will see that args is a tuple of arguments passed to the callback method. Error in question was passing 1 arg to a method with none. Will show up in system console as an error.

>>> bpy.types.SpaceView3D.draw_handler_add(
draw_handler_add(callback, args, region_type, draw_type)
.. method:: draw_handler_add(callback, args, region_type, draw_type)
Add a new draw handler to this space type.
It will be called every time the specified region in the space type will be drawn.
Note: All arguments are positional only for now.
:param callback:
   A function that will be called when the region is drawn.
   It gets the specified arguments as input.
:type callback: function
:param args: Arguments that will be passed to the callback.
:type args: tuple
:param region_type: The region type the callback draws in; usually ``WINDOW``. (:class:`bpy.types.Region.type`)
:type region_type: str
:param draw_type: Usually ``POST_PIXEL`` for 2D drawing and ``POST_VIEW`` for 3D drawing. In some cases ``PRE_VIEW`` can be used. ``BACKDROP`` can be used for backdrops in the node editor.
:type draw_type: str
:return: Handler that can be removed later on.
:rtype: object

Attempt to add every draw call back possible. Has to be a redraw of the type specified to fire the callback. I doesn't relentlessly fire.

import bpy
from bpy.types import SpaceView3D, Region
class DrawClass:
    def __init__(self, context):
        for rt in  Region.bl_rna.properties['type'].enum_items.keys():
            for d in ('POST_PIXEL', 'POST_VIEW', 'PRE_VIEW', 'BACKDROP'):

                        self.dcb, (rt, d,), rt, d)
                    print("No dcb for", rt, d)

    def dcb(self, rt, d):
        print("Testing dcb:", rt, d)

if __name__ == "__main__":
  • $\begingroup$ Oh..., I mistakenly assumed that SpaceView3D's draw handler gets called at each OpenGL draw of the viewport, not just when the view is manipulated. I didn't touch the viewport when testing this out so the callback wasn't being called. Thanks for clarifying this! $\endgroup$
    – user56873
    Commented Dec 24, 2019 at 12:41
  • 1
    $\begingroup$ NP.. never tried the other options eg 'PRE_VIEW' and 'UI' ... be a good idea to add a combo of each to see which one suits best. $\endgroup$
    – batFINGER
    Commented Dec 24, 2019 at 12:45

You must log in to answer this question.