4

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)

Armored Wolf
  • 831
  • 6
  • 17

1 Answers1

6

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()

brockmann
  • 12,613
  • 4
  • 50
  • 93