[suggestion] ui element instantiation, add_subview
@omz, It would be great if all ui elements could be instantiationed with all attributes as named params as well as a parent param. If the parent param is a valid view then add_subview(parent) is called by ui.
I think this would clean up a lot of code when making views in code. Just a idea
How is parent different from superview?
@ccc, yes parent is the wrong word. Maybe just 'view' is a better name. But the idea being you can in one statement define a ui element and have it added as a subview. But could be a subview of the parent. My meaning is you would not assume that you wanted it added to the superview, rather explicitly state what view it would be added to as a subview
Not a bad idea. Because of the way
ui.Viewused to work (fixed set of attributes), it would require quite a few changes to support this directly, but it's fairly easy to write a factory function that instantiates views with arbitrary attributes, and (optionally) adds them to an existing parent view:
def make_view(cls=ui.View, **kwargs): if not issubclass(cls, ui.View): raise TypeError('cls must be a subclass of ui.View') v = cls() for name in sorted(kwargs.keys()): value = kwargs[name] if name in ('parent', 'superview') and isinstance(value, ui.View): value.add_subview(v) else: name = name.strip('_') setattr(v, name, value) return v
main_view = ui.View(frame=(0, 0, 400, 400)) make_view(ui.SegmentedControl, parent=main_view, frame=(10, 10, 380, 32), tint_color='green', _segments=['foo', 'bar', 'baz'], selected_index=1) main_view.present('sheet')
Now, you may be wondering why I prefixed the
segmentsattribute with an underscore, and then stripped that underscore in
make_view. This is basically just a trick to force that the attributes are set in a specific order, specifically, that the
segmentsattribute is set before the
selected_indexbecause setting the selected index doesn't work if there are no segments yet. There aren't a lot of cases where the order matters, but I happened to come across one of them when I wrote this example, and this was the easiest workaround I could think of.
@omz , ok, that is cool also.i was thinking another way.
self.btn = ui.Button(any_named_attr = x, and so on, etc..., parent = self)
So that one statement you could define a ui.Button entirely (of course all params would have default values) and if the parent or view param (whatever to call it) is not None, then the add_subview would be called by ui.
So in my meaning each ui element could possibly only need one statement to have 100% of its attrs set and be added to a view. I say could possibly, because a lot of the time you are going to calculate and set the frame in the layout method.
Oh, I thought I was going to get it straight between the eyes. 2 seconds after I wrote the above post, I was thinking.....
Is it possible to do self.lb = ui.Label(name = 'xxx').add_subview(self)
But, I just tried it and you can't. Maybe a better way to go
@omz I did this and is very nice. Of course, better if in ui module.
# coding: utf-8 import ui import MakeView v = ui.View(frame= (0,0,540,576)) x = MakeView.make_view(ui.Label, frame = (0,0,v.width, 44), text = 'hello', background_color = 'purple', text_color = 'white', alignment = ui.ALIGN_CENTER, font = ('<system-bold>', 22) , parent = v) v.present('sheet')
And sorry, I didn't get your first comment about changing it easily. I get it now. As long as It does not create more legacy code for you, Then would be nice to have it in the std API.