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.
Programmable keys in Pythonista for quickly wrench actions execution
-
If you want to add buttons starting on the left:
btn=ui.Button( frame=((index)*40,22,40,40))Or, just increase the index large enough to go where you want.
One problem may be that parts of the toolbar get rebuilt when switching tabs. So, your button could end up underneath the default, but I'm not sure.
I did implement a swipe gesture on the built in wrench (i.e swipe down pops up a quick shortcut menu) but because the button keeps getting reset, this doesn't stick.
This also seems to be the issue with trying to customize the coming keyboard, as it seems to get rebuilt dynamically. -
@Matteo You could execute this code after
tb=get_toolbar(main_view)
to remove (definitely) the left button (x=8.0 on my iPad, to be tried on iPhone).
But to retrieve it, you'll need to restart Pythonista (I guess)..
Correction: button comes back when Pythonista is back in foregroundfor v in tb.subviews(): if v._get_objc_classname().startswith(b'OMBarButton'): print(v.indexInSuperview(),v.frame().origin.x) # just to be sure if v.frame().origin.x == 8.0: v.removeFromSuperview()```
-
Thank you @JonB and @cvp for help! I performed some tests and you can see the output in images below:
First:
Second (after touching Pythonista Run button):
Third (after touching the user button at left):
Fourth (after touching the long bar):
In the last image it seems that the long bar (that is a series of little squares) doesn't work properly because when I touch it, the action is the same user obtains when touches the filename of the script (it shows the list of definitions in the current script).
The last button , at the right, works properly (it hides in a good way the built-in wrench button) and touching it, the action prints 'hello' in the console as expected (it is a very very simple test).Have you some ideas why the long bar can't hide the built-in button (that is the filename of the current script) as the single button at the right?
If you need to test the code I will post here a link.
Thanks
Regards -
@Matteo I had also remarked that the "file name button" has priority, but no idea why.
-
@cvp Hi, ok, it's strange because the top bar should be entirely programmed with user keys.
Maybe the field where there is the script name is reserved or it is so big that even if I touch the long bar, I accidentally touch the built-in filename button.Do you know if we can increase the size of user buttons? I will try to increase the width of the long bar in order to see if I can hide completely the built-in button of the script name.
Thanks
Regards -
-
@cvp Hi, sorry but I can't use your hint to increase the width/hight of my user key (I most likely ignore something).
What I'd like to do is to create a button larger/higher than the one user can add searching in icons database "Images" (where user finds a lot of images for buttons, like Ionicons Black, Ionicons White, Planet Cute, Platformer Art, etc...). I already use the larger built-in icons (256 instead of 24 or 32) but I'm trying to increase more and more the button (more than 0.45 mm of height), in order to hide entirely the area of the screen from button |+| to button |> (I want to hide also ios wifi icon and current time above the long bar in image Third of my previous post). For now I'm interested only about portrait use of iPhone (that is the fastest way for me to run scripts with one hand when I'm away from home).
I don't know if the new big long bar will work, preventing me from accidentally touching of the filename built-in button (Anyway, I doubt I can succeed because it seems that the button dimension does not affect the Pythonista built-in filename button). But I will try if I know how to increase the size of buttons.
And an other question: how can you add text to user buttons or change background colour of them in order to have several buttons with different colours and different text inside to recognize them and their actions easly?
Thank you
Bye -
@Matteo What you call "my hint" is only change the apphack.py code to set x and with of button.
btn=ui.Button( frame=(tb.size().width - tb.rightItemsWidth()-(index+1)*40,22,40,40)) Becomes btn=ui.Button( frame=(tb.size().width - tb.rightItemsWidth()-(index+1)*40-20,22,60,40))
-
@Matteo text, its color and border are set by
btn.title = 'laaarge' btn.tint_color = 'white' btn.border_width = 1 btn.background_color = 'blue'
-
An option for keeping user buttons on top is
tb.superview().addSubview_(btn)
at the end of create_toolbar_button
-
@JonB btn or btn_obj?
-
@JonB I need to go up twice...
tb.superview().superview().addSubview_(btn_obj)
-
@JonB Wonderful, it works! I used the code:
tb.superview().superview().addSubview_(btn_obj)
(Thanks @cvp)
Really, @JonB how can you know these things? However, now I have a code that creates, every time I launch Pythonista, two buttons, at left and at right of upper bar. The left one, if touched, shows six little squares buttons (one button for one action). The right one, if touched, hides the six buttons.
Maybe you will find this a little easy, but for me it is a great thing ;-)Two questions:
- How can I program the left button in order to use it both for showing and hiding of the six user buttons? I mean, when the six buttons are showed, touching the left button should hide them; when the six buttons are hidden, touching the left button should show them.
- Can Pythonista execute automatically a script every time user changes iphone screen from portrait to landscape and viceversa? Inside 'pythonista_startup.py'?
@cvp thank you for info about buttons size. But the last two values in:
btn=ui.Button( frame=((index)*40,22,40,40))
are a bit strange for me: what do they mean (40 and 40)?
And I can't show any text inside my buttons. Can you kindly show me what and where I must add some code for button text? Let's imagine the user button must show the text "Copy": what should I do in the following code (JonB's apphack.py) to add text inside the button?# coding: utf-8 ''' A set of tools to add or delete custom buttons from the toolbar. This may not be super robust, but seems to work ok. Button objects and actions are saved so they survive global clearing, but thid has not been tested extensively. If a function relies on imports that occured outside of the function, these might dissappear -- user must make sure those modules are added to a module that is kept by pythonista, such as anything in site-packages, or name starting with __ ''' from objc_util import * import ui,console import weakref from functools import partial w=ObjCClass('UIApplication').sharedApplication().keyWindow() main_view=w.rootViewController().view() def get_toolbar(view): #get main editor toolbar, by recursively walking the view sv=view.subviews() for v in sv: if v._get_objc_classname().startswith(b'OMTabViewToolbar'): return v tb= get_toolbar(v) if tb: return tb def create_toolbar_button(action,image,index=0,tag=''): '''create a button on main toolbar, with action, imagename, index location, and string tagname. button and action are stored in __persistent_views[index]. tag allows finding view using tb.viewFromTag_(hash(tag)) (old idea)''' assert(callable(action)) tb=get_toolbar(main_view) global __persistent_views try: __persistent_views except NameError: __persistent_views={} #check for existing button in this index and delete if needed remove_toolbar_button(index) #add new button to the left of the rightbuttons. index 0 is next to left buttons, index 1 is further left, etc #store so it is not cleared. btn=ui.Button( frame=((index)*40,22,40,40)) btn.flex='L' btn.image=ui.Image.named(image) btn.action=action btn_obj=ObjCInstance(btn) btn_obj.tag=hash(tag) __persistent_views[index]=(btn,action,tag) tb.addSubview_(btn_obj) #JonB suggestion: tb.superview().superview().addSubview_(btn_obj) return btn def remove_toolbar_button(index): global __persistent_views try: btn,action,tag=__persistent_views.pop(index) btn.action= None ObjCInstance(btn).removeFromSuperview() except KeyError: pass if __name__=='__main__': def run_script(sender): '''run a script without clearing glbals''' import editor exec(editor.get_text(),globals()) remove_toolbar_button(0) create_toolbar_button(run_script,'iow:stop_256',0,'execfile')
Thank you so much!
Regards -
- .....,40,40) = width and height of the button
Edit: if you add a text like 'copy' you could need to set a bigger width and no image - as explained in one of my previous posts, you can set the text, its color, etc...
btn.image = ... btn.title = 'copy' btn.action = ...
- .....,40,40) = width and height of the button
-
@Matteo If your actual
left button doesbtn1.hidden = True
right button does
btn1.hidden = False
Your future unique button could do
btn1.hidden = not btn1.hidden
-
@Matteo We would have to experiment, but a custom view class
layout
method, would get called upon rotation, assuming flex=`w'. -
https://gist.github.com/37e5115840bef9b898dba36ba3df5802
Here is an experiment, where I add a half-button at the top right corner of the screen (at battery icon), in the status bar. Tapping there pops down a menu. Tapping again makes it dissappear. You could adjust the size of this as desired. This seems somewhat cleaner, visually. At 32 height, buttons are tappable, and also could stay displayed without interfering with normal ui buttons. Things stay anchored correctly even with rotation.
This lives in the statusbar window, so is over top of everything, which might not be desirable... it might make more sense to keep the button in the statusbar, but keep the overlay in the editor, though this way, it is available even in console. You also have the whole screen to work with, if you want, so are not confined to the toolbar.
-
@JonB Whaaaaaaa, as usual
-
@JonB Impressive, really! Thank you! I still find hard to believe that you can do certain things with Pythonista.
I tried your script in my iPhone 4'' screen and works very well.
I've seen that the user buttons remain in the three Pythonista windows: file editor, text editor and python console. It is a wonderful thing in my opinion: in this way user can have quickly access to favourite actions in file editor window (for actions an files and folders) and in text editor window (for actions on text and strings).Your code is a little incomprehensible to me but I will try to adapt your work in order to use it with my frequent actions.
Thank you @JonB and @cvp for all help!
Regards -
@JonB Hi! Sorry but I can't solve a little problem with your code.
The procedure I follow to reproduce the issue is:
- full restart of Pythonista,
- run your script in order to show the half button in right up corner,
- write a simple python script like
print('hello')
, - execute the script with |> button (it automatically goes to console window),
- return to text editor windows and touch the half button,
- it return
NameError: global name 'ui' is not defined
.
Note that the user buttons in action bar work well: if I touch for example the button 'Blah' it print in console the number 50.0. The problem is that I can't anymore hide the full action bar.
When you have time, can you kindly test the issue? Thank you very much,
Regards
PS: I use Pythonista 3.1 (301016).