4
$\begingroup$

I would like to achieve the layout of this panel but I'm having some issues. The example is from blender's Bevel Operator. As far as I can tell it's just an Enum Property without the enum_flag since only Vertices or Edges can be selected at a time:

enter image description here

First attempt:

layout = self.layout
row = layout.row()
row.label(text='My Prop');  row.prop(self, 'enum_prop', expand=True)

Looks pretty similar, just gotta align the label to the right.

enter image description here

Second Attempt:

layout = self.layout
row = layout.row()
split = row.split(factor=0.4)

left_col  = split.column(align=True)
right_col = split.column(align=True)
        
left_col.alignment  = 'RIGHT'
right_col.alignment = 'CENTER'

left_col.label(text='My Prop'); right_col.prop(self, 'enum_prop', expand=True)

enter image description here

Well, I managed to align things into columns but my Enum Prop is suddenly vertical. I figured I wasn't giving it enough room with the Split factor but that wasn't the case. How can I achieve the result from the first image?

(Label aligned to the Right + Horizontal Enum Prop)

EXTRA INFO:

If anyone is wondering, here is how I created the property:

enum_items = [  ('ON',  'On',  'Description1'), 
                ('OFF', 'Off', 'Description2')]
                            
enum_prop: EnumProperty(name='My Prop', default='OFF', items=enum_items)
$\endgroup$

1 Answer 1

6
$\begingroup$

Just set layout.use_property_split property in your draw method to True:

def draw(self, context):
    layout = self.layout
    layout.use_property_split = True
    layout.use_property_decorate = False  # No animation.
    ...

Custom Panel

Example based on the add-on template from: How to create a custom UI?

enter image description here

bl_info = {
    "name": "Add-on Template",
    "description": "",
    "author": "p2or, brockmann",
    "version": (0, 0, 3),
    "blender": (2, 80, 0),
    "location": "3D View > Tools",
    "warning": "", # used for warning icon and text in addons panel
    "wiki_url": "",
    "tracker_url": "",
    "category": "Development"
}


import bpy

from bpy.props import (StringProperty,
                       BoolProperty,
                       IntProperty,
                       FloatProperty,
                       FloatVectorProperty,
                       EnumProperty,
                       PointerProperty,
                       )
from bpy.types import (Panel,
                       Menu,
                       Operator,
                       PropertyGroup,
                       )


# ------------------------------------------------------------------------
#    Scene Properties
# ------------------------------------------------------------------------

class MyProperties(PropertyGroup):

    my_bool: BoolProperty(
        name="Enable or Disable",
        description="A bool property",
        default = False
        )

    my_int: IntProperty(
        name = "Int Value",
        description="A integer property",
        default = 23,
        min = 10,
        max = 100
        )

    my_float: FloatProperty(
        name = "Float Value",
        description = "A float property",
        default = 23.7,
        min = 0.01,
        max = 30.0
        )

    my_float_vector: FloatVectorProperty(
        name = "Float Vector Value",
        description="Something",
        default=(0.0, 0.0, 0.0), 
        min= 0.0, # float
        max = 0.1
    ) 

    my_string: StringProperty(
        name="User Input",
        description=":",
        default="",
        maxlen=1024,
        )

    my_path: StringProperty(
        name = "Directory",
        description="Choose a directory:",
        default="",
        maxlen=1024,
        subtype='DIR_PATH'
        )

    my_enum: EnumProperty(
        name="Dropdown:",
        description="Apply Data to attribute.",
        items=[ ('OP1', "Option 1", ""),
                ('OP2', "Option 2", ""),
               ]
        )

# ------------------------------------------------------------------------
#    Panel in Object Mode
# ------------------------------------------------------------------------

class OBJECT_PT_CustomPanel(Panel):
    bl_label = "My Panel"
    bl_idname = "OBJECT_PT_custom_panel"
    bl_space_type = "VIEW_3D"   
    bl_region_type = "UI"
    bl_category = "Tools"
    bl_context = "objectmode"   


    @classmethod
    def poll(self,context):
        return context.object is not None

    def draw(self, context):
        layout = self.layout
        layout.use_property_split = True
        layout.use_property_decorate = False  # No animation.

        scene = context.scene
        mytool = scene.my_tool

        layout.prop(mytool, "my_bool")
        layout.prop(mytool, "my_enum", expand=True)
        layout.prop(mytool, "my_int")
        layout.prop(mytool, "my_float")
        layout.prop(mytool, "my_float_vector")
        layout.prop(mytool, "my_string")
        layout.prop(mytool, "my_path")


# ------------------------------------------------------------------------
#    Registration
# ------------------------------------------------------------------------

classes = (
    MyProperties,
    OBJECT_PT_CustomPanel
)

def register():
    from bpy.utils import register_class
    for cls in classes:
        register_class(cls)

    bpy.types.Scene.my_tool = PointerProperty(type=MyProperties)

def unregister():
    from bpy.utils import unregister_class
    for cls in reversed(classes):
        unregister_class(cls)
    del bpy.types.Scene.my_tool


if __name__ == "__main__":
    register()

Custom Operator

It's basically the same for the redo panel, you would have to create an extra row though:

enter image description here

import bpy


class SimpleOperator(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.simple_operator"
    bl_label = "Simple Object Operator"
    bl_options = {'REGISTER', 'UNDO'}
    
    my_enum: bpy.props.EnumProperty(
        name="Dropdown:",
        description="Apply Data to attribute.",
        items=[ ('OP1', "Option 1", ""),
                ('OP2', "Option 2", "")])
                
    my_float: bpy.props.FloatProperty(
        name = "Float Value",
        description = "A float property",
        default = 23.7,
        min = 0.01,
        max = 30.0)
        
        
    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):
        print(self.bl_idname)
        return {'FINISHED'}

    def draw(self, context):
        layout = self.layout
        layout.use_property_split = True
        layout.use_property_decorate = False  # No animation.

        row = layout.row(align=True)
        row.prop(self, "my_enum", expand=True)
        layout.prop(self, "my_float")

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


def unregister():
    bpy.utils.unregister_class(SimpleOperator)


if __name__ == "__main__":
    register()

    # test call
    #bpy.ops.object.simple_operator()
$\endgroup$
2
  • $\begingroup$ Thanks, it works perfectly. I will study the link you shared more closely. Blender's built-in templates were not as helpful. Thanks again! $\endgroup$ Commented Nov 9, 2020 at 15:25
  • $\begingroup$ Glad I could help @ArmoredWolf $\endgroup$
    – brockmann
    Commented Nov 9, 2020 at 16:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .