Not all actions made with the Blender Python API cause Blender to immediately redraw the screen. Therefore, quite often it is necessary to force a screen refresh so that the user immediately sees all the changes.
For example, let’s draw a circle on the 3D viewport area using the “gpu” module.
1 2 3 4 5 6 7 8 9 10 11 |
import bpy import gpu from gpu_extras.presets import draw_circle_2d shader = gpu.shader.from_builtin('3D_SMOOTH_COLOR') def draw(): shader.bind() draw_circle_2d((0.0, 0.0), (0.0, 1.0, 1.0, 1.0), 1.0, segments=20) draw_handler = bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_VIEW') |
If we execute this code from the Blender Text Editor by pressing the “execute script” button with arrow, at first we will not see any changes on the viewport. To see the drawn circle, we need to move the cursor to the 3D viewport area and perform some action, for example, change the scale by turning the mouse wheel. At this moment, the viewport is updated, and we see all the changes at once.
To save the user the trouble of manually refreshing the screen, we can force a screen redraw by executing the following code:
1 2 |
for area in bpy.context.screen.areas: area.tag_redraw() |
After its execution, all open areas, including the viewport, will be updated.
To redraw only the 3D viewport area, we can limit the call by area type:
1 2 3 |
for area in bpy.context.window.screen.areas: if area.type == 'VIEW_3D': area.tag_redraw() |
This code will cause only the 3D viewport area to be redrawn.
Screen redrawing can also be done with the redraw_timer() operator.
1 |
bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1) |
Although this operator is provided by the developers to measure screen redraw speed, it redraws the entire screen as it runs, which is what we need.