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.
ui elements and private storage
-
Apologies if this has been discussed or been addressed. Many years ago, I programmed in SuperCard, basically HyperCard on steroids. But one stand out thing for me back then was each GUI item had a tag property for private storage. I think it would be great if every ui element had a (empty) list, called whatever(let's say tag, for the want of a better word). Also if this property/attribute was available in the ui editor to set, would be great. Very similar idea to the left_button_items or right_...
Maybe python exposes ways to attach dynamic storage/methods to existing memory objects, I don't know the language well enough to know.
I could also see that in the ui editor with some preceding token It could attempt to parse python code. So in the editor ui item attributes you have the tag field, this could be simply be set with the string: ['red', 'blue', 'green'] or possibly something like: @python range(1,100) both resulting in lists.
I think the way I have expressed my idea is rough around the edges. But I think there is something in there. I am hesitant to write things like this, in fear of being though of as an idiot. But my intention is to contribute not to distract. -
Perhaps it would be best if you could create a
github repo
of some code that would use the feature that you suggest and then by looking at that code together, we could determine the best path forward. -
I will just drop this question for the moment @ccc. I can't write code for it as the functionality is not there. But I think my inexperience with Python led me to ask the question. I can easily see developer storage is simple when implementing ui with classes. Also, it appears that you can add your own attributes to classes or functions. So just reading about this now and trying to understand it. Anyway, I will do my research and testing first. But thanks for your reply
-
@Phuket2: Correct me if I’m wrong, but you want to set UI element attributes, right? If so, the way you do that is by setting the object attributes directly. For example, if you have a variable
my_label
that is a UI label, you can set its text shown when the script is run by writingmy_label.text = "your text here"
. You can do the same with all of the UI classes’ attributes, just look at theui
module documentation to see what is possible. -
@Gerzer, thanks for the reply. Sorry, if my jargon is incorrect . But, I am not trying to set UI elements attributes, rather I am trying to extend the class of say ui.Button to have a new attribute. Maybe to store a list, some state etc...
My original comment was a suggestion about all ui elements getting a extra attribute (r/w) that the programmer could use. As I mentioned, in the old days of HyperCard/SuperCard, they had this concept, they just called it a Tag Property. It was very useful for keeping some related data with any GUI object. I also suggested that it would be great if it was added uniformly to all the ui objects, meaning you could easily iterate all objects looking at that property, knowing it exists. As a Python beginner , I am not sure what I suggest is a good Python style or not. Seems to be very strong views about Python coding practices. Which I think is a good thing. Will just take some time to learn.
Given its easy to wrap up a view into a class, could also say my point is mute, as you can store anything in the class you like.
I also see you can extend classes various ways with Python. I have tried something like
import type ... #trying to extend ui.Button to have a new Method tag() def add_new_method_to_btn(self): v = self.view btn = v['button1'] self.btn = types.MethodType(self.tag,btn, ui.Button) ``` Due to my lack of experience, I haven't got far yet. But as this is a hobby for me, I am happy to keep plugging away (best way to learn). I have also looked at doing it with @property decorator, again fail at this point. I understand trying to extend the class myself is a Python language issue and that stackflow is a better place to discuss that issue. Just talk about it here more to explain my original suggestion. But again, thank you for reply. Still not sure I have conveyed my point clearly enough. But I have tried :)
-
As you said yourself, you can extend the class by creating a subclass of it:
import ui class my_Button(ui.Button): def __init__(self): super(my_button,self).__init__() # calls the constructor of ui.Button # here you can add your new tags self.tag = [] def tag_set(self, tag): self.tag = tag
Now you can use my_Button instead of ui.Button and you can access its tag variable:
button = my_Button([all the arguments needed]) button.tag_set = 'I am a button with custom data!' print button.tag >>> 'I am a button with custom data!'
I hope this helps you :)
-
Moe, please excuse my ignorance, but sub classing a class is not the same as extending a class. Hmmm, maybe it is. Is tricky :). I tried your example, did not work for me. But is late here now, so I will try again tomorrow. But thanks for the info.
-
@Moe,
I copied your class my_button(ui.Button)... Into my code. But get the error string,
TypeError:Error when calling the metaclass bases type '_ui.button' is not an acceptable base typeCan't see what I could have done wrong.
-
Most
ui
classes can't be subclassed from Python. The only exceptions are generic view classes, likeui.View
orui.ScrollView
. -
@dgelessus,why is it like that?is it something about Xcode? In a way I think it's frightening what can be done with Python language. But at same time is liberating
-
The
ui
classes are written in (Objective-)C, not Python. C classes behave differently than "normal" Python classes in a few ways, one of them being that they cannot be subclassed by default. (This isn't specific to custom modules - some unusual Python types likefunction
orNoneType
can't be subclassed either. I have no experience at all in writing Python modules in C, so I can't tell you any exact details or reasons for this behavior. -
ui.View
can be subclassed, and that is a common way to add the functionality you are describing. If you want a view that behaves like a button, except with some sort of internal variables, you can simply have a custom View which has a single button subview.If you want to get fancy, you can make this view behave just like a Button, by
@property
ing the key attributes of a Button so that you can access them from your custom view.As an example, see https://github.com/jsbain/uicomponents/blob/master/uiCheckBox.py, which is a simple checkbox custom view. It contains a single button, which is added automatically when the checkbox is instantiated. The button action toggles the internal
value
attribute, and displays an X if the value is True. You can see how theenabled
property is overridden with aproperty
decorator, which sets or reads from the internal Button'senabled
attribute. If you masquerade a few key properties, you can effectively subclass most of the non-subclassable ui components to add additional functionality. A neat thing about Custom Views is that you can add them to other views via the ui editor.The other approach for this type of thing is to have a controller class that is used as the target for all of your ui's actions. That way, actions can set whatever internal variables you want, then other actions can access those.