To elaborate on @Hikariztw 's answer
Using the code from https://blender.stackexchange.com/a/141207/15543 as an example.
Update to the property group def.
class MaterialSlot(PropertyGroup):
def get_name(self):
return self.get("name", "Foo")
def set_name(self, value):
oldname = self.get("name", "Foo")
self["name"] = value
print(oldname, value)
material : PointerProperty(type=bpy.types.Material)
name : StringProperty(
default="Foo",
get=get_name,
set=set_name)
Note the example code uses the material name in list UI class. Change to show item
in draw method to show collection item name instead.
layout.prop(item, "name", text= "", emboss=False, icon_value=layout.icon(ma))
Python console code, added a new scene material slot. It is given the default name "Foo". Updating the name to "Bar", in this case via console, same if done via UI, and the setter is called. Which prints old name "Foo" and new name "Bar"
>>> s = C.scene.material_slots.add()
>>> s.name
'Foo'
>>> s.name = "Bar"
Foo Bar
and again from "Bar" to "Choo"
>>> s.name = "Choo"
Bar Choo
But here is the "rub" re the property default value. The PropertyGroup
class already has a name attribute. When a new item is first added, it doesn't use the name property default of "Foo", but rather defaults to "".
>>> C.scene.material_slots.clear()
>>> s = C.scene.material_slots.add()
>>> s.name
'Foo'
>>> C.scene.material_slots.keys()
['']
ie collection has a material_slots[""]
member rather than material_slots["Foo"]
However if we set it implicitly, it picks up as expected... which is usual practice I suppose.
>>> s.name = "Foo"
Foo Foo
>>> C.scene.material_slots.keys()
['Foo']
EDIT re comment
so when I update the list element's name I need to find all objects
with the original element name and then change it to the new name
For example above, to set all items with old name to new name, do this on a custom property level too. Add something like below to set_name
method above.
if oldname != value:
same = [s for s in self.id_data.material_slots
if oldname == s.get("name", "Foo")]
for s in same:
s["name"] = value