1
$\begingroup$

I want to create nice-looking auto-adjusting UIList with three columns of data inside. Some of the values in columns are different in length. They are: float value, unit (usually 2-3 chars) and name of the corresponding object (could be longer, but nvm).

Here is the sample code: First, I have a collection object defined like this:

class Area(bpy.types.PropertyGroup):
    id = IntProperty()
    area = FloatProperty(default=0.0, description='Area measured')
    atxt = StringProperty(default='0.0',description='Area converted to text and formatted')
    unit = StringProperty(default='',description='Unit item choosen from UnitTypes')
    name = StringProperty(default='',description='Object name which area is calculated')

Then I have a draw_item function, which is defined like this:

class AreaItemList(UIList):
    def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
        if self.layout_type in {'DEFAULT', 'COMPACT'}:
#           line = ('%-12s %4s %-s' % (item.atxt,item.unit,item.name))
#           layout.label(text = line)

            layout.prop(item,"atxt",emboss=False,text='')
            layout.prop(item,"unit",emboss=False,text='')
            layout.prop(item,"name",emboss=False,text='')
        elif self.layout_type in {'GRID'}:
            pass

Please note the commented section: it does work, but looks ugly, and there is no align in columns because of variable char length. So, the question is: - how to make aligned columns in UIList?

It could be either by using layout.split (but it's hard to predict the split ratio, and there are three columns, and by the way - the documentation is pretty poor about this layout function), or either by using monospaced font and string formatting. How to do this? Any ideas? Look of the list for the code from the comment: http://storage3.static.itmages.com/i/16/0423/h_1461384717_4797711_d3f6576ba9.jpeg

$\endgroup$
2
$\begingroup$

By default when you place multiple items on the same row blender will give each item an equal portion of the row eg. three items get 33% of the row each. Due to the fluid nature of blender's layout, we can't specify an exact size of each column, they will get resized as the user resizes the layout.

You can use UILayout.split() to alter the percentage of a row that an item uses. To expand on my earlier answer to include an example of splitting three columns you can get the following result.

enter image description here

Note that the split works on the allocated space, the first split turns a row into two columns, the first column gets the percentage size of 60%, the remaining items then use the remaining 40%. I have then used split again so that the second column gets 30% of the available space - that is 30% of the remaining width after the first split not the entire row.

def draw(self, context):
    measure_size = 0.6
    unit_size = 0.3
    box = self.layout.box()
    col = box.column()

    row = col.split(percentage=measure_size)
    row.label(text='9.3000168000e+03')
    row = row.split(percentage=unit_size)
    row.label(text='in')
    row.label(text='Cube')

    row = col.split(percentage=measure_size)
    row.label(text='7.176e+00')
    row = row.split(percentage=unit_size)
    row.label(text='yd')
    row.label(text='Cube')
| improve this answer | |
$\endgroup$
  • $\begingroup$ Thank you for that answer. I think I have to stick with that method, although I wonder if there will be possible to format all columns in a way they could adjust themselves when I put something significantly longer into any column. In the other words, is this possible to mimic the behavior of for example html table, which adjusts it's content automatically? Here if I define constant split as .6, it will remain as such and then I have no way to adjust column lenghts in any way to fit their content. Do you think it's possible? $\endgroup$ – piotao Apr 23 '16 at 20:12
  • $\begingroup$ Blender adds vertical scrollbars to long lists but not horizontal scrollbars to wide lists. Users can also zoom the properties area and alter DPI to make everything larger/smaller. That is the dynamic nature of the blender UI. If the user resizes their properties to an inch wide then they won't see long items, it won't matter if you have it set to 60% or 300 pixels. You could calculate the width based on text length instead of using a fixed size. $\endgroup$ – sambler Apr 24 '16 at 4:09
  • $\begingroup$ I understand this behavior and I love it. However in this case I would like to put 'denser' data into small region than it would be in default. So is there any way to decrease the space created between columns with split? Even in your example in the picture there is a significant space between columns, which for small panel size is a waste and causes text labels to hide behind dots (...). I would like to keep those columns but without such wide margins in them. $\endgroup$ – piotao Apr 24 '16 at 5:22
  • 1
    $\begingroup$ I don't think we can alter the padding around each item. $\endgroup$ – sambler Apr 24 '16 at 6:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.