Dropdown-List in Custom Menu

Reaching out for some help again… this time I am trying to display a dropdown-list in a custom menu. I have found some threads on that topic, but somehow I am not able to adjust the code right. The following is what I have:

class OPERATIONS_PANEL(bpy.types.Panel):
    bl_label = "Label"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "scene"                                                                                                    

    dropdown_list = EnumProperty(
        name="Selection",
        items=(
               ('1', 'Skeleton', 'Export Skeleton to JSON-file'),
               ('2', 'Animation', 'Export Animation to JSON-file'),
            ),
        )

    def draw(self, context):
        layout = self.layout

        row = layout.row()
        row.props(self, "dropdown_list")

Unfortunately this displays exactly nothing and I am lost :o.

Any ideas?

you can’t declare properties in panel subclasses. You can only register them globally on bpy.types or define them as operator properties. As you wanna add them to a panel, you need to go with global props.


class OPERATIONS_PANEL(bpy.types.Panel):
    bl_label = "Label"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "scene"                                                                                                    


    def draw(self, context):
        layout = self.layout

        row = layout.row()
        row.props(context.scene, "dropdown_list"


def register():
    bpy.utils.register_class(OPERATIONS_PANEL)

    bpy.types.Scene.dropdown_list = EnumProperty(
        name="Selection",
        items=(
               ('1', 'Skeleton', 'Export Skeleton to JSON-file'),
               ('2', 'Animation', 'Export Animation to JSON-file'),
            ),
        )

def unregister():
    bpy.utils.unregister_class(OPERATIONS_PANEL)
    del bpy.types.Scene.dropdown_list

if __name__ == '__main__':
    register()

For IO addons based on the Export/Import Helper util classes, use operator properties instead.

Thanks for your fast response. The good thing is I have learned something… the bad, I am still not seeing the dropdown-list. I have no clue why.

After playing a bit around it seems like I run mostly into this error message:

AttributeError: ‘_RestrictContext’ object has no attribute ‘scene’

As far as I understand this is due to a API change in one of the more recent updates. Since this update it is no longer possibe to access “scene” as before.

Maybe it is a bit too much asked, but would it be possible for someone to adjust the following code taken from the API documentation for Blender 2.5 to show how it has to look for 2.68?

#----------------------------------------------------------

File scene_props.py

#----------------------------------------------------------
import bpy
from bpy.props import *

Store properties in the active scene

def initSceneProperties(scn):
bpy.types.Scene.MyInt = IntProperty(
name = “Integer”,
description = “Enter an integer”)
scn[‘MyInt’] = 17

bpy.types.Scene.MyFloat = FloatProperty(
    name = "Float", 
    description = "Enter a float",
    default = 33.33,
    min = -100,
    max = 100)

bpy.types.Scene.MyBool = BoolProperty(
    name = "Boolean", 
    description = "True or False?")
scn['MyBool'] = True

bpy.types.Scene.MyEnum = EnumProperty(
    items = [('Eine', 'Un', 'One'), 
             ('Zwei', 'Deux', 'Two'),
             ('Drei', 'Trois', 'Three')],
    name = "Ziffer")
scn['MyEnum'] = 2

bpy.types.Scene.MyString = StringProperty(
    name = "String")
scn['MyString'] = "Lorem ipsum dolor sit amet"
return

initSceneProperties(bpy.context.scene)

Menu in UI region

class UIPanel(bpy.types.Panel):
bl_label = “Property panel”
bl_space_type = “VIEW_3D”
bl_region_type = “UI”

def draw(self, context):
    layout = self.layout
    scn = context.scene
    layout.prop(scn, 'MyInt', icon='BLENDER', toggle=True)
    layout.prop(scn, 'MyFloat')
    layout.prop(scn, 'MyBool')
    layout.prop(scn, 'MyEnum')
    layout.prop(scn, 'MyString')
    layout.operator("idname_must.be_all_lowercase_and_contain_one_dot")

The button prints the values of the properites in the console.

class OBJECT_OT_PrintPropsButton(bpy.types.Operator):
bl_idname = “idname_must.be_all_lowercase_and_contain_one_dot”
bl_label = “Print props”

def execute(self, context):
    scn = context.scene
    printProp("Int:    ", 'MyInt', scn)
    printProp("Float:  ", 'MyFloat', scn)
    printProp("Bool:   ", 'MyBool', scn)
    printProp("Enum:   ", 'MyEnum', scn)
    printProp("String: ", 'MyString', scn)
    return{'FINISHED'}    

def printProp(label, key, scn):
try:
val = scn[key]
except:
val = ‘Undefined’
print("%s %s" % (key, val))

Registration

bpy.utils.register_module(name)

I think this would be appropriate in 2.6x:

#----------------------------------------------------------
# File scene_props.py
#----------------------------------------------------------

import bpy
from bpy.props import *


class UIPanel(bpy.types.Panel):
    """Menu in left sidebar of the 3D View (UI region)"""
    bl_label = "Property panel"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"
 
    def draw(self, context):
        layout = self.layout
        scn = context.scene
        layout.prop(scn, 'MyInt', icon='BLENDER', toggle=True)
        layout.prop(scn, 'MyFloat')
        layout.prop(scn, 'MyBool')
        layout.prop(scn, 'MyEnum')
        layout.prop(scn, 'MyString')
        layout.operator("idname_must.be_all_lowercase_and_contain_one_dot")
 

class OBJECT_OT_PrintPropsButton(bpy.types.Operator):
    """The button prints the values of the properites in the console"""
    bl_idname = "idname_must.be_all_lowercase_and_contain_one_dot"
    bl_label = "Print props"
 
    def execute(self, context):
        scn = context.scene
        print()
        printProp("Int:    ", 'MyInt', scn)
        printProp("Float:  ", 'MyFloat', scn)
        printProp("Bool:   ", 'MyBool', scn)
        printProp("Enum:   ", 'MyEnum', scn)
        printProp("String: ", 'MyString', scn)
        return{'FINISHED'}    


def printProp(label, key, scn):
    val = getattr(scn, key, "Undefined")
    print("%-10s %s" % (key, val))


def initProperties():
    """Store properties in Scene type"""
    
    bpy.types.Scene.MyInt = IntProperty(
        name = "Integer", 
        description = "Enter an integer",
        default=17)
 
    bpy.types.Scene.MyFloat = FloatProperty(
        name = "Float", 
        description = "Enter a float",
        default = 33.33,
        min = -100,
        max = 100)
 
    bpy.types.Scene.MyBool = BoolProperty(
        name = "Boolean", 
        description = "True or False?",
        default=True)
 
    bpy.types.Scene.MyEnum = EnumProperty(
        items = [('Eine', 'Un', 'One'), 
                 ('Zwei', 'Deux', 'Two'),
                 ('Drei', 'Trois', 'Three')],
        default='Zwei',
        name="Ziffer")
 
    bpy.types.Scene.MyString = StringProperty(
        name="String",
        default="Lorem ipsum dolor sit amet")


def removeProperties():
    del bpy.types.Scene.MyInt
    del bpy.types.Scene.MyFloat
    del bpy.types.Scene.MyBool
    del bpy.types.Scene.MyEnum
    del bpy.types.Scene.MyString


# Registration

def register():
    bpy.utils.register_module(__name__)
    initProperties()
    
def unregister():
    bpy.utils.unregister_module(__name__)
    removeProperties()
    
if __name__ == '__main__':
    register()

Thank you so much CoDEmanX, that looks like it is working… let me see if I can “abuse” your code now ;-).