Help creating widgets

Hi all!

I need to create a list-like widget. I have looked into the Blender default panels sources, but I find them hard to dissect, and would like a more straightforward example.


Either of those two types of widgets would be fine for my purpose. Basically I need to be able to re-popoulate the list with some filenames, on a button click, and then be able to tell which item on the list is selected. So my guess is that I would need to dynamically generate a property (enum?) from which I would be able to get the current list selection?

Could anyone help me with the code (or explanation) for how would the property / panel combo look like in this case, or point me to some resources that deal with such issue.

i think i have an old example for collection
but not working anymore can you help to make it work again!


 
 
import bpy
## class where the custom properties for the Collection will be nested
## (each entry of the collection will derive its Properties from this Class
## and can hold own values for each property)
class PropertyGroup(bpy.types.IDPropertyGroup):
 pass
 
 
bpy.types.Object.mychosenObject = bpy.props.StringProperty()
 
## create CollectionProperty and link it to the property class
bpy.types.Object.myCollection = bpy.props.CollectionProperty(type = PropertyGroup)
bpy.types.Object.myCollection_index = bpy.props.IntProperty(min = -1, default = -1)
## create Properties for the collection entries:
PropertyGroup.mystring = bpy.props.StringProperty()
PropertyGroup.mybool = bpy.props.BoolProperty(default = False)
 
 
 
## create operator to add or remove entries to/from  the Collection
class OBJECT_OT_add_remove_Collection_Items(bpy.types.Operator):
 bl_label = "Add or Remove"
 bl_idname = "collection.add_remove"
 
 add = bpy.props.BoolProperty(default = True)
 
 def invoke(self, context, event):
  add = self.add
  obj = context.object
  collection = obj.myCollection
  if add:
   collection.add()         # This add at the end of the collection list
  else:
   index = obj.myCollection_index
   collection.remove(index)       # This remove on item in the collection list function of index value
 
 
 
class OBJECT_PT_ObjectSelecting(bpy.types.Panel):
 
 bl_label = "Object Selecting"
 bl_space_type = "PROPERTIES"
 bl_region_type = "WINDOW"
 bl_context = "object"
 
 def draw(self, context):
  obj = context.object
  layout = self.layout
 
  ##show collection in Panel:
  row = layout.row()
  row.template_list(obj, "myCollection", obj, "myCollection_index")        # This show list for the collection
  ##show add/remove Operator
  col = row.column(align=True)
  col.operator("collection.add_remove", icon="ZOOMIN", text="")         # This show a plus sign button
  col.operator("collection.add_remove", icon="ZOOMOUT", text="").add = False     # This show a minus sign button
 
  ##change name of Entry:
  if obj.myCollection:
   entry = obj.myCollection[obj.myCollection_index]
   layout.prop(entry, "name")
 
   ##show self created properties of myCollection
   layout.prop(entry, "mystring")
   layout.prop(entry, "mybool")
 
  ### search prop to search in myCollection:
  layout.prop_search(obj, "mychosenObject",  obj, "myCollection")
 
 
 
 

this add a list which can be dynamically change

hope it is what your looking for

thanks and a happy 2.5

Thanks, this is probably what I’m looking for

I’ll check it and report

but not working anymore can you help to make it work again!

You need to register classes:

bpy.utils.register_class(class_name)

and use bpy.types.PropertyGroup instead of bpy.types.IDPropertyGroup.

i tried to register classes here
but still get a error on IDgroup thing

i’m not tha familiar with this type of collection thing and mostly idgroup
so can you correct it and re load sample

thanks and happy 2.5

I tried to get somewhere with that code, but I’ll need some more help.
For now I can’t even register the property group, it complains that the filelist object can’t register.

import bpy
from bpy.props import PointerProperty, CollectionProperty, StringProperty, BoolProperty, IntProperty

# to hold multiple properties that fit together
class MyPropertyGroup(bpy.types.IDPropertyGroup):
    filelist = CollectionProperty([], type=StringProperty)
    listindex = IntProperty(min=0, default=0)
    chosen = StringProperty()
    
bpy.utils.register_class(MyPropertyGroup)

The reasoning behind this code is that I want to have a property group, that encapsulates all the properties of that list panel I want - ie. a collection of string properties (filenames), the number of the current list index and the value (name of file) of the currently selected item. Does this make sense?

How are collection properties properly initialized (I passed an empty list, because at this point there is no data to fill)? And especially; how are collections of properties iterated and manipulated (remove, add, etc…)

RickyBlender, http://www.pasteall.org/19556/python

Thanks andreymi, that code works! (PropertyGroup needs to be replaced with IDPropertyGroup)

Now things are a little clearer :slight_smile:

BTW, I don’t see a remove() method on CollectionProperty mentioned in the API (it wont let me to post links), how I’m supposed to know that remove() exists?

first tried the pastall one and in 35161 it does not work !
any idea why and how to correct this?

and there is a + - way did you read at the beginning of the script the instructions ?

i hope it will work again it is a good example
wish there was other like that to learn more about it

happy 2.5

What does it say?
I had to rename PropertyGroup to IDPropertyGroup to make it work (build 34855M)

i did change to IDpropr

but now i get this error

Traceback (most recent call last):
File “collection351611.py”, line 5, in <module>
AttributeError: ‘RNA_Types’ object has no attribute ‘IDPropertyGroup’

don’t know do you an older veison around 35161 ?
and at graphical there is only up to around 35256 !
so don’t think it’s the problem

i’ll try later on to get a new vresion today
but may be you should update to a lter version to get the same problem
34855 is a little old by now

thanks

And what does it say if you use PropertyGroup?

There are obviously some class name differences between revisions, but the overall logic behind building this GUI example should be the same.

i don’t get any error message
nothing but no panel!

happy 2.5

Does anybody know how do I connect an enum button set to some operator? I know how to show enum set like a property, but I want that an operator is triggered each time the user choses some option. Like for example in the material buttons, different previews are triggered depending on your choice:

RickyBlender, I have no clue why it doesn’t work for you…

These are events, and these we are waiting for the developpers to implement. It is in the TO DO list and Ton thinks in a month probably they will start with that. It is very necessary because a lot of former scripts can’t be ported until events are programmed.

ok here is the version i tested in 35161
and get no error s and no panel

may be somone can test this and tell me if you get same results


 
import bpy
 
## class where the custom properties for the Collection will be nested
## (each entry of the collection will derive its Properties from this Class
## and can hold own values for each property)
 
class PropertyGroup(bpy.types.PropertyGroup):
 pass
 
bpy.utils.register_class(PropertyGroup) 
 
 
bpy.types.Object.mychosenObject = bpy.props.StringProperty()
 
## create CollectionProperty and link it to the property class
bpy.types.Object.myCollection = bpy.props.CollectionProperty(type = PropertyGroup)
bpy.types.Object.myCollection_index = bpy.props.IntProperty(min = -1, default = -1)
## create Properties for the collection entries:
PropertyGroup.mystring = bpy.props.StringProperty()
PropertyGroup.mybool = bpy.props.BoolProperty(default = False)
 
 
 
## create operator to add or remove entries to/from  the Collection
class OBJECT_OT_add_remove_Collection_Items(bpy.types.Operator):
 bl_label = "Add or Remove"
 bl_idname = "collection.add_remove"
 
 add = bpy.props.BoolProperty(default = True)
 
 def invoke(self, context, event):
  add = self.add
  obj = context.object
  collection = obj.myCollection
  if add:
   collection.add()         # This add at the end of the collection list
  else:
   index = obj.myCollection_index
   collection.remove(index)       # This remove on item in the collection list function of index value
   
   
 
class OBJECT_PT_ObjectSelecting(bpy.types.Panel):
 
 bl_label = "Object Selecting"
 bl_space_type = "PROPERTIES"
 bl_region_type = "WINDOW"
 bl_context = "object"
 
 def draw(self, context):
  obj = context.object
  layout = self.layout
  
  ##show collection in Panel:
  row = layout.row()
  row.template_list(obj, "myCollection", obj, "myCollection_index")        # This show list for the collection
  ##show add/remove Operator
  col = row.column(align=True)
  col.operator("collection.add_remove", icon="ZOOMIN", text="")         # This show a plus sign button
  col.operator("collection.add_remove", icon="ZOOMOUT", text="").add = False     # This show a minus sign button
  
  ##change name of Entry:
  if obj.myCollection:
   entry = obj.myCollection[obj.myCollection_index]
   layout.prop(entry, "name")
   
   ##show self created properties of myCollection
   layout.prop(entry, "mystring")
   layout.prop(entry, "mybool")
  
  ### search prop to search in myCollection:
  layout.prop_search(obj, "mychosenObject",  obj, "myCollection")
    
    
bpy.utils.register_class(OBJECT_PT_ObjectSelecting) 
bpy.utils.register_class(OBJECT_OT_add_remove_Collection_Items) 
#bpy.utils.register_class(PropertyGroup) 
 
 
 
 
 

thanks happy 2.5

I get the panel ok in rev35205 properties window object panel … but it gets buggy from there… the add button needs to return something eg (‘FINISHED’)

I think it also needs to have some sort of default text like “group” when you add groups.

Apart from that this looks very handy.

@Bao2, thanks for the explanation. Indeed events are indispensable

EDIT:
I compiled Blender just now (r35275) and the list example andreymi posted works as expected without errors.

ok got another version and seem to work now

but when click on plus get error

location:<unknown location>:-1
TypeError: calling class function: Function.result expected a string enum or a
et of strings in (‘RUNNING_MODAL’, ‘CANCELLED’, ‘FINISHED’, ‘PASS_THROUGH’), no
NoneType
location:<unknown location>:-1

any idea how to coret this ?

thanks

set up a bl_location var and
return {‘FINISHED’} from your operator method.