I have a StringProperty
that I want to show the name of the selected object. Currently, I update the property by invoking an operator manually from a panel. However, I want the property to be updated automatically every time the selected object in the viewport changes.
What is the best way to achieve this?
I have considered running a modal operator, which checks the selection change all the time. However, that does not seem like an optimal solution. I have also tried playing around with handlers (bpy.app.handlers.scene_update_post
as mentioned here), but it seems to have the same result as a modal operator (constant checking in infinite loop). Is it possible to trigger the update only when the selection changes by some callback? Or alternatively, when the right mouse button is clicked (assuming selection only happens this way)?
Edit, for clarification:
I specifically need a StringProperty
to be updated, and not just a regular text label. This is because the StringProperty
(and other properties) will display some specific information about the selected object, which the user then can change to change the selected object.
My current code, where the StringProperty
is updated manually by click:
import bpy
# Define string property.
class MyGroup(bpy.types.PropertyGroup):
bpy.types.Scene.my_string = bpy.props.StringProperty(name='my_string')
# Define operator to change string property.
last_selection = []
class UpdateStringOperator(bpy.types.Operator):
bl_idname = "update.mystring"
bl_label = ""
def invoke(self, context, event):
global last_selection
if bpy.context.selected_objects != last_selection:
last_selection = bpy.context.selected_objects
bpy.context.scene.my_string = bpy.context.selected_objects[0].name
return {'FINISHED'}
# Draw property and operator.
class MyPanel(bpy.types.Panel):
...
def draw(self, context):
layout = self.layout
layout.row().prop(context.scene, "my_string")
layout.row().operator("update.mystring", text="Update")
# Register.
def register():
bpy.utils.register_module(__name__)
def unregister():
bpy.utils.unregister_module(__name__)
if __name__ == "__main__":
register()