test_template_list.py
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# Blender2.77a
import bpy
def creat_not_jyuufuku_name(name, name_set, num):
new_name = ""
if '.' in name:
split_name = name.split('.')
if split_name[-1].isdigit():
new_name = ".".join(split_name[0:-1]) + ".{:03d}".format(num)
else:
if split_name[-1] == "":
new_name = name + "{:03d}".format(num)
else:
new_name = ".".join(split_name) + ".{:03d}".format(num)
else:
new_name = name + ".{:03d}".format(num)
if new_name in name_set:
return creat_not_jyuufuku_name(new_name, name_set, num+1)
return new_name
def get_my_string(self):
return self["name"]
def set_my_string(self, value):
self["name"] = value
tl = bpy.context.window_manager.test_ui_list.test_list
if len(tl) > 1:
s = set()
result = [x.name for x in tl if x.name in s or s.add(x.name)]
if len(result):
number = 1
self["name"] = creat_not_jyuufuku_name(value, s, 1)
class MyTestGroup(bpy.types.PropertyGroup):
name = bpy.props.StringProperty(get=get_my_string, set=set_my_string)
int_val = bpy.props.IntProperty()
bpy.utils.register_class(MyTestGroup)
class MyCollectionProperty(bpy.types.PropertyGroup):
active_index = bpy.props.IntProperty()
test_list = bpy.props.CollectionProperty(type=bpy.types.MyTestGroup)
def add(self):
item = self.test_list.add()
item.name = "name"
item.int_val = 10
self.active_index = len(self.test_list)-1
def remove(self):
if len(self.test_list):
self.test_list.remove(self.active_index)
if len(self.test_list)-1 < self.active_index:
self.active_index = len(self.test_list)-1
if self.active_index < 0:
self.active_index = 0
def move(self, index1, index2):
if len(self.test_list) < 2:
return
if 0 <= index1 < len(self.test_list):
if 0 <= index2 < len(self.test_list):
self.test_list.move(index1, index2)
self.active_index = index2
def clear(self):
self.test_list.clear()
class MyUIListAddItemOperator(bpy.types.Operator):
bl_idname = "view3d.my_uilist_add_item"
bl_label = "Add Item"
def execute(self, context):
context.window_manager.test_ui_list.add()
return {'FINISHED'}
class MyUIListRemoveItemOperator(bpy.types.Operator):
bl_idname = "view3d.my_uilist_remove_item"
bl_label = "Remove Item"
def execute(self, context):
context.window_manager.test_ui_list.remove()
return {'FINISHED'}
class MyUIListMoveItemOperator(bpy.types.Operator):
bl_idname = "view3d.my_uilist_move_item"
bl_label = "Move Item"
type = bpy.props.StringProperty(default='UP')
def execute(self, context):
ui_list = context.window_manager.test_ui_list
if self.type == 'UP':
ui_list.move(ui_list.active_index, ui_list.active_index-1)
elif self.type == 'DOWN':
ui_list.move(ui_list.active_index, ui_list.active_index+1)
return {'FINISHED'}
class MyUIListClearItemOperator(bpy.types.Operator):
bl_idname = "view3d.my_uilist_clear_item"
bl_label = "Clear Item"
def execute(self, context):
context.window_manager.test_ui_list.clear()
return {'FINISHED'}
class MY_UL_test_group_list(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
if self.layout_type in {'DEFAULT', 'COMPACT'}:
layout.prop(item, "name", text="", emboss=False, icon_value=icon)
elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label(text="", icon_value=icon)
class UIListTestPanel(bpy.types.Panel):
bl_label = "UIList Test Panel"
bl_idname = "VIEW3D_PT_ui_list_test"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
def draw(self, context):
layout = self.layout
ui_list = context.window_manager.test_ui_list
row = layout.row()
col = row.column()
col.template_list("MY_UL_test_group_list", "", ui_list, "test_list", ui_list, "active_index", rows=1)
col = row.column(align=True)
col.operator("view3d.my_uilist_add_item", icon='ZOOMIN', text="")
col.operator("view3d.my_uilist_remove_item", icon='ZOOMOUT', text="")
col.operator("view3d.my_uilist_move_item", icon='TRIA_UP', text="").type = 'UP'
col.operator("view3d.my_uilist_move_item", icon='TRIA_DOWN', text="").type = 'DOWN'
layout.operator("view3d.my_uilist_clear_item", text="All Clear")
if len(ui_list.test_list):
row = layout.row()
row.prop(ui_list.test_list[ui_list.active_index], "name")
row = layout.row()
row.prop(ui_list.test_list[ui_list.active_index], "int_val")
def register():
bpy.utils.register_class(MyCollectionProperty)
bpy.utils.register_class(MyUIListAddItemOperator)
bpy.utils.register_class(MyUIListRemoveItemOperator)
bpy.utils.register_class(MyUIListMoveItemOperator)
bpy.utils.register_class(MyUIListClearItemOperator)
bpy.utils.register_class(MY_UL_test_group_list)
bpy.utils.register_class(UIListTestPanel)
bpy.types.WindowManager.test_ui_list = bpy.props.PointerProperty(type=MyCollectionProperty)
def unregister():
del bpy.types.WindowManager.test_ui_list
bpy.utils.unregister_class(UIListTestPanel)
bpy.utils.unregister_class(MY_UL_test_group_list)
bpy.utils.unregister_class(MyUIListAddItemOperator)
bpy.utils.unregister_class(MyUIListRemoveItemOperator)
bpy.utils.unregister_class(MyUIListMoveItemOperator)
bpy.utils.unregister_class(MyUIListClearItemOperator)
bpy.utils.unregister_class(MyCollectionProperty)
#bpy.utils.unregister_class(MyTestGroup)
if __name__ == "__main__":
register()
Copiez-le et collez-le dans l'éditeur de texte de Blender et exécutez-le.
Vous pouvez ajouter et supprimer des données à partir des boutons + et-. Déplacez l'élément sélectionné avec les boutons haut et bas. Vous pouvez tout supprimer avec le bouton Tout effacer.
Un opérateur distinct est préparé pour ajouter et supprimer des données, et placé à côté de celui-ci afin qu'il ait la même apparence que les autres panneaux. Lors de son utilisation, il est préférable de placer le bouton de suppression dans un endroit éloigné.
Vous devez éviter vous-même les noms en double.
Il semble que le contenu de la liste soit affiché dans draw_item () de la classe MY_UL_test_group_list. Vous pouvez l'afficher en remplaçant "nom" par "int_val".
L'endroit où vous pouvez le modifier directement en double-cliquant est le même.
Je ne pense pas avoir beaucoup de chance d'utiliser template_list (), mais j'en avais un peu besoin, alors j'ai essayé de savoir comment l'utiliser.
move ()
et clear ()
de Collection Property
comme boutons.