Does anyone know of a way to force a redraw of the controls in a panel? I have a separate python thread running (which happens to be monitoring some other threads running in my C++ DLL–but that’s beside the point) and I want certain info to become visible in a GUI panel when that thread terminates.
You could try the bpy.types.Area.tag_redraw() method. I would have given the link to the API doc, but the forum does not seem to want that. The same method exists for bpy.types.Screen also.
Another way would be to update a property that is displayed in your panel via layout.prop(). AFAIK these are watched and cause a redraw on update.
bw,
Skim
Hmmm excellent suggestions. I tried the tag_redraw but it looks like trying to access
bpy.context.window.screen.areas
from within a thread says that bpy.context.window is a NoneType. Also I found out the hard way a bit earlier in my adventures in accessing blender data from a thread, that trying to change a property from within a thread gets the infamous write-error message (like when you try to change a prop from within a draw method). I probably should have mentioned that in the first post! Anyway what I’ve got at the moment is text label in the panel that displays the asynchronous data, and a do-nothing operator button just above it that says “Mouse over to update data” (because a redraw is necessary to highlight the button when the mouse is over it). Pretty clunky, I know, but maybe I’ll have to live with it.
I’m toying with just posting a WM_PAINT to the Blender GUI and be done with it, but that seems a bit clunky, too, and of course only works on Windows. But then I can almost guarantee all my users will be Windows-only, anyway, because I’ve no need to port that Windows DLL code to Linux.
Well here’s a way that is very clunky, only works on Windows, probably prone to fail with later versions of Blender, and won’t work if the Blender window title bar isn’t just “Blender” when it first starts up… but at least it ~sometimes~ works and should fail gracefully when it does fail:
from ctypes import *
BlenderWin=0
#somewhere that is executed at start-up:
global BlenderWin
if not BlenderWin:
user32=windll.user32
BlenderWin=user32.FindWindowW("GHOST_WindowClass","Blender")
# in the thread:
global BlenderWin
user32=windll.user32
user32.PostMessageW(Win,0xF,0,0) # post a WM_PAINT
So I guess I’ll use that but keep the do-nothing operator button that says “Mouse over to update data”