Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Loading pyui files into the root level of a custom class
-
ui.View
s have asuperview
attribute that points to their parent view. If I'm understanding you correctly this would do what you want:import ui def load_into_parent(view, filename): view.superview.add_subview(ui.load_view(filename))
-
This post is deleted! -
@dgelessus, I am not sure. But it looks promising. Off to test it.
-
Guys,
Thanks for your help. However niether approach flattens out the view. It appears to graphically, but is still a sub_view of the parent . When it's a sub_view, the addressing of the objects are via the subview. I have tried to demonstrate with the code below.
Does not matter if a pyui file or multiple files.
You can't call v.superview.add_subview on your topmost view. Still does not matter, you can call it on a lower class, same results, you are adding a new view with its own addressing spaceLook, again. Maybe I am missing something simple. But I think this would be valuable in building ui's.
# coding: utf-8 import ui class v1(ui.View): def __init__(self): self.name = 'aux_view' lb = ui.Label(name = 'lb') lb.text = 'some text' self.add_subview(lb) class MyClass(ui.View): def __init__(self, f): self.frame = f self.background_color = 'white' v = v1() # i would like to do something like.... # self.merge_this_view(v1) self.add_subview(v) # line below fails, even though the view is # merged visually, its not merged, its a still # a sub_view. #self['lb'].text = 'some text' # this line will work self['aux_view']['lb'].text = 'new text' # i know, i can save attributes etc to access # the subviews eaisier. i really just wanted it # flattened out into a single view in this case. if __name__ == '__main__': f = (0,0,540, 576) mc = MyClass(f) mc.present('sheet')
-
what exactly are you trying to achieve? You want to design the ui in the editor, but have it contained within your custom class, so that you can encapsulate callbacks, etc?
The is exactly what the Custom View field in the ui editor is for. The docs are a little vague about this, but the idea is you have a custom View class, which you refernce in the ui editor. When you call load_view, the class is instantiated, and the loaded pyui associated with the instance.
-
@JonB, yes I have done that before from the ui. I think @ccc helped me getting it going. For the moment, I am working on my cell class that is used by the VirtualView. A part of the flexibility I wanted for the cell is to be able to load a pyui file as its view. I can get that working. But the bigger idea in my mind is just composing cells/views from multiple views, memory or file based. But to have those elements be in the same addressing space.
I can also see many times you would not want this. When you want the container view and its subviews to be a subview.
But I think times when you would like view merged into views (hierarchy flatted out). -
I am looking at ui.py now, will see what I can see from there
-
ok, played around a bit, here are a few thoughts:
You set the CustomView class in the ui editor, then you use load_view() which will instantiate your custom class. Button callbacks, if they are class instance variables, need to be set inside your custom class did_load, because you don't have access to the instantiated object yet.Actually, this used to be true, but since in 1.6 the action attribute is simply eval'd, it is possible using some
inspect
trickery to gain access to the custom class instance!def this(): import inspect fb=inspect.currentframe().f_back while fb.f_back.f_code.co_name != 'load_view_str': fb=fb.f_back return fb.f_locals['v']
allows one to use this().some_callback_method as the action attribute for buttons, etc inside the ui editor -- this() returns the top level custom class instance, which has already been built but simply is in the process of having subviews instantiated. This might make custom class code a lot cleaner (usually, button actions, various delegates, etc all have to be set inside of did_load, which makes for a big pile of initializations)
-
@JonB, I was also playing. I am sure not as good as you. But if use self = ui.load_view('somefile.pyui', bindings = self), I seem to get the view loaded into the root, but it does not display. I don't understand the stackframe param.
Is this possibly a more direct way? -
what would "merging" a view really mean? You just want the subviews of the loaded view as subviews of your existing view?
for sv in otherview.subviews: myview.add_subview(sv)
But what to do about the loaded top Views attributes, like bg color, etc. What to do when subview names conflict? Complicated pyui's might have custom classes that depend on the top level attribs. You could copy these over of course, but this starts getting pretty fragile.
Your VirtualViewCell sounds more like a container -- much like a ScrollView or TableViewCell, for example. If you want to standardize addressing, consider placing all user content into a
content
attribute, similar to TableViewCells. You could also override the__getitem__
and perhapssubviews
method, so that named or indexed calls to other subviews are redirected to yourcontent
... though i wouldnt recommend that approach. -
@JonB , I get your point. But I would imagine any merged views attributes would not override the parents attributes. Duplicate subview names a little more tricky. I guess could just refuse to load, raise an error.
But I do see the problems with this approach.
Thanks for your help. I will keep trying. As you say, don't want anything that is fragile. Needs to be robust. -
here is an example of a custom view defined by a pyui. not what you are looking for now, but thought i'd share this method of setting the action from within the custom view itself.
https://gist.github.com/jsbain/1da126b6d60dfa15055d -
@JonB, thanks.
I can see @omz could do it in the future. It's a little funky how all the calls to _view_from_dict sort of cascade. I made a copy of ui to ui2, passed self all the way to _view_from_dict. Then Added the parsed items to self.add_subview.
It sort of works.
I just tried to do some minimal things without hardly changing the code.
However _view_from_dict returns a view, also so other things I don't understand. So a little rework would be required, but possible.
I know I could copy the code and roll my own.... But not worth it. Eventually it would break.