omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    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

    Pythonista
    3
    18
    417
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • P
      philippe last edited by

      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 defined

      KEYBOARD_NUMBERS is supposed to be one of multiple registered constants.
      So I mind what’s the problem with it ?

      cvp 1 Reply Last reply Reply Quote 0
      • cvp
        cvp @philippe last edited by

        @philippe use

        ui.KEYBOARD_NUMBERS
        
        P 1 Reply Last reply Reply Quote 0
        • P
          philippe @cvp last edited by

          @cvp
          Okay
          No more errors messages
          Nervetheless it didn’t change nothing during execution ?!

          cvp 2 Replies Last reply Reply Quote 0
          • cvp
            cvp @philippe last edited by cvp

            @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)
            

            tap here to see keyboard

            1 Reply Last reply Reply Quote 0
            • cvp
              cvp @philippe last edited by

              @philippe No feedback?

              P 1 Reply Last reply Reply Quote 0
              • P
                philippe @cvp last edited by

                @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 ….

                cvp 1 Reply Last reply Reply Quote 0
                • cvp
                  cvp @philippe last edited by

                  @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

                  P 1 Reply Last reply Reply Quote 0
                  • P
                    philippe @cvp last edited by

                    @cvp
                    Thank you @cvp
                    You’re helpful
                    Do you know how to be root anyway?

                    cvp 1 Reply Last reply Reply Quote 0
                    • cvp
                      cvp @philippe last edited by

                      @philippe said

                      Do you know how to be root anyway?

                      What do you mean?

                      P 1 Reply Last reply Reply Quote 0
                      • P
                        philippe @cvp last edited by

                        @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

                        cvp 1 Reply Last reply Reply Quote 0
                        • cvp
                          cvp @philippe last edited by

                          @philippe I think that exec is not supported in Pythonista. What do you want to do?

                          P 1 Reply Last reply Reply Quote 0
                          • P
                            philippe @cvp last edited by

                            @cvp
                            Just run a program with one of those exec() command, it’s simple ….

                            cvp 1 Reply Last reply Reply Quote 0
                            • cvp
                              cvp @philippe last edited by cvp

                              @philippe from where do you want to run a script? Normally, we edit a script and run it via the play button

                              You can also read this old topic

                              P 1 Reply Last reply Reply Quote 0
                              • P
                                philippe @cvp last edited by

                                @cvp
                                Yes but I would like to run a script from another script

                                cvp 1 Reply Last reply Reply Quote 0
                                • cvp
                                  cvp @philippe last edited by cvp

                                  @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)
                                  
                                  P 1 Reply Last reply Reply Quote 0
                                  • P
                                    philippe @cvp last edited by

                                    @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

                                    cvp ccc 2 Replies Last reply Reply Quote 0
                                    • cvp
                                      cvp @philippe last edited by cvp

                                      @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.

                                      1 Reply Last reply Reply Quote 0
                                      • ccc
                                        ccc @philippe last edited by

                                        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.

                                        1 Reply Last reply Reply Quote 1
                                        • First post
                                          Last post
                                        Powered by NodeBB Forums | Contributors