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.
Textfield keyboard_type
-
Hello 👋🏻
On the way to understanding Pythonista UI i try to manipulate textfields
In the doc I’ve found the keyboard_type attribute ; don’t know what it really does but the fact is an error message when trying to set , like :txfd.keyboard_type = KEYBOARD_NUMBERS
NameError: name 'KEYBOARD_NUMBERS' is not definedKEYBOARD_NUMBERS is supposed to be one of multiple registered constants.
So I mind what’s the problem with it ? -
@philippe use
ui.KEYBOARD_NUMBERS
-
@cvp
Okay
No more errors messages
Nervetheless it didn’t change nothing during execution ?! -
@philippe said
Nervetheless it didn’t change nothing during execution ?!
What do you mean?
If you mean that numeric keyboard is not really a numeric keyboard, you are true. It is only a normal keyboard where the "123" key has been pressed.
If you want a real numeric keyboard, with only digits, you need to build it yourself as Pythonista allows you to do.
If you want that, tell me, I've done it for another guy in this forum, some years ago.Or try this little script
import ui from objc_util import * from math import cos,sin,pi from random import random def SetTextFieldPad(tf, pad=None, clearButtonMode=False, undo_redo_pasteBarButtons=False, textfield_did_change=None, broken=False): if not pad: pad = [{'key':'1'},{'key':'2'},{'key':'3'}, {'key':'back space','icon':'typb:Delete'}, {'key':'new row'}, {'key':'4'},{'key':'5'},{'key':'6'}, {'key':'delete','icon':'emj:Multiplication_X'}, {'key':'new row'}, {'key':'7'},{'key':'8'},{'key':'9'}, {'key':'⏎', 'SFicon':'return'},#done','icon':'emj:Checkmark_3'}, {'key':'new row'}, {'key':'nul'},{'key':'0'},{'key':'nul'},{'key':'.'}] tfo = ObjCInstance(tf).textField() # UITextField is subview of ui.TextField def key_pressed(sender): if sender.title == 'test': return tfb = sender.TextField tfobjc = ObjCInstance(tfb).textField() cursor = tfobjc.offsetFromPosition_toPosition_(tfobjc.beginningOfDocument(), tfobjc.selectedTextRange().start()) if sender.name == 'delete': if cursor <= (len(tfb.text)-1): tfb.text = tfb.text[:cursor] + tfb.text[cursor+1:] elif sender.name == 'back space': if cursor > 0: #if tfb.text != '': tfb.text = tfb.text[:cursor-1] + tfb.text[cursor:] cursor = cursor - 1 elif sender.name == '⏎':#done': tfb.end_editing() return else: tfb.text = tfb.text[:cursor] + sender.title + tfb.text[cursor:] cursor = cursor + 1 if textfield_did_change: textfield_did_change(tfb) # set cursor cursor_position = tfobjc.positionFromPosition_offset_(tfobjc.beginningOfDocument(), cursor) tfobjc.selectedTextRange = tfobjc.textRangeFromPosition_toPosition_(cursor_position, cursor_position) # design your keyboard # pad = [{key='functionnality',title='title',icon='icon'},...] # new row => new row # nul => no key # back space => left delete # delete => right delete # done => discard the keyboard # other => append the character # count the maximum width of rows row_max_length = 0 row_length = 0 for pad_elem in pad: if pad_elem['key'] == 'new row': if row_length > row_max_length: row_max_length = row_length row_length = 0 else: row_length = row_length + 1 if row_length > row_max_length: row_max_length = row_length v = ui.View() db = 50 dd = 10 x0 = (ui.get_screen_size()[0]-row_max_length*db-(row_max_length-1)*dd)/2 x = x0 y = dd for pad_elem in pad: if pad_elem['key'] == 'new row': y = y + db + dd x = x0 elif pad_elem['key'] == 'nul': x = x + db + dd else: b = ui.Button() b.name = pad_elem['key'] b.background_color = 'white' # or any other color b.tint_color = 'black' b.corner_radius = 10 b.title = '' b.font = ('<system>',32) if 'icon' in pad_elem: b.image = ui.Image.named(pad_elem['icon']).with_rendering_mode(ui.RENDERING_MODE_ORIGINAL) elif 'SFicon' in pad_elem: o = ObjCClass('UIImage').systemImageNamed_(pad_elem['SFicon']) wsf,hsf = o.size().width,o.size().height with ui.ImageContext(db,db) as ctx: o.drawInRect_(CGRect(CGPoint(0.1*db,0.1*db), CGSize(0.8*db,0.8*db))) b.image = ctx.get_image() elif 'title' not in pad_elem: b.title = pad_elem['key'] if 'title' in pad_elem: b.title = pad_elem['title'] b.frame = (x,y,db,db) if broken: r = random() # generate between 0 and 1 # angle between -10° and 10° a = (pi/180) * (r-0.5)*20 rot = CGAffineTransform(cos(a),-sin(a),sin(a),cos(a),0,0) ObjCInstance(b).transform = rot b.TextField = tf # store tf as key attribute needed when pressed if 'action' in pad_elem: b.action = pad_elem['action'] else: b.action = key_pressed v.add_subview(b) x = x + db + dd y = y + db + dd v.width = ui.get_screen_size()[0] app = UIApplication.sharedApplication().keyWindow() bot = app.safeAreaInsets().bottom v.height = y + bot # view of keyboard retain_global(v) # see https://forum.omz-software.com/topic/4653/button-action-not-called-when-view-is-added-to-native-view tfo.setInputView_(ObjCInstance(v)) #print(dir(ObjCInstance(v))) # color of cursor and selected text tfo.tintColor = UIColor.redColor().colorWithAlphaComponent(0.5) # clear button tfo.clearButtonMode = clearButtonMode # comment both lines to keep undo/redo/paste BarButtons above keyboard if not undo_redo_pasteBarButtons: tfo.inputAssistantItem().setLeadingBarButtonGroups(None) tfo.inputAssistantItem().setTrailingBarButtonGroups(None) if __name__ == '__main__': import ui tf = ui.TextField() SetTextFieldPad(tf)#,broken=True) tf.text = '' tf.width = 400 tf.present('sheet') tf.begin_editing() tf.wait_modal() #print(tf.text)
-
@philippe No feedback?
-
@cvp
Too much complicated for my purpose
I am a beginner, one step before another
See, I have many questions to ask and I also have to understand things before practicing.
For example, I cannot run the functions exec() because of a permission denied error
So how can I make myself root ?
Etc …. -
@philippe ok, understood. If standard keyboards types do not meet your request, you would have to pass via ObjectiveC, thus more complex... Anyway, welcome in this forum. 6 years ago, I didn't even know what Python was. Thus, enjoy
-
-
-
@cvp
When i try one of the functions exec() I get a permission denied message
In fact it seems that i am not getting the right of execution. The os.getuid() function tells that i am the 501 uid
I suppose i should have root uid
What do you think -
@philippe I think that exec is not supported in Pythonista. What do you want to do?
-
@cvp
Just run a program with one of those exec() command, it’s simple …. -
-
@cvp
Yes but I would like to run a script from another script -
@philippe Terminate your first script by this code which will start your other script one second later, allowing the first script to really end its process
Of course, you have to replace my example by your own script path
from objc_util import * import os import ui def t(): path = os.path.expanduser('~/Documents/MesApps/bd.py') arg = '' I3=ObjCClass('PYK3Interpreter').sharedInterpreter() # run a script like in wrench menu (path, args, reset env yes/no) I3.runScriptAtPath_argv_resetEnvironment_(path, [arg], True) ui.delay(t,1)
-
@cvp
What a mess !!
Why can’t we use the os module ??
Why do i haven’t the rights on MY phone ?I WANT TO START A SCRIPT WITH THE SYSTEM OR EXEC COMMANDS IN CONSOLE MODE OR IN A SCRIPT OF MINE AS I CAN DO IT ON A MAC OR A PC .
If this is not possible or if I must invoke some dark unknown hidden class to do it….. I resign
Dommage
-
@philippe on a Mac or a Pc you launch directly a script, on iOS the only app you launch is Pythonista and this works as an interpreter to understand and run your script. Don't hope same features for that and you have to accept some limitations, like no exec command
Your script has to run under Pythonista thus why do you want to start it in console mode? If you don't want to edit your script (when it is ended and bug free), you can define it as a Pythonista tool and launch it from the wrench button. Or you can launch it via an icon on your iDevice via a shortcut. On iOS, there is no real command mode.
-
Why do i haven’t the rights on MY phone ?
The Apple Security Guideline for iOS devices limits the rights that apps have. This means there is less malware on these devices but that safety comes at the cost of constraining what system services are available to developers. Android offers more access but some would argue is less safe than iOS.