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.


    'Enter'-keypress/softpress to call action in custom form input

    Pythonista
    2
    11
    3506
    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.
    • cvp
      cvp @boegh last edited by cvp

      @boegh try something like

      import ui
      import dialogs
      from console import set_color
      
      class mytf_delegate(object):
        global c
        def textfield_did_end_editing(self, textfield):
          c.done_action('sender') # unused parameter
        def textfield_did_change(self, tf):
          c.values[tf.name] = tf.text
      
      def myform_dialog(title='', fields=None,sections=None, done_button_title='ok'):
          global c
      
          sections = [('', fields)]
          c = dialogs._FormDialogController(title, sections, done_button_title=done_button_title)
          
          for s in range(0,len(c.sections)):
            for i in range(0,len(c.cells[s])):			# loop on rows of section s
              cell = c.cells[s][i]									# ui.TableViewCell of row i
              tf = cell.content_view.subviews[0] 		# ui.TextField of value in row
              tf.delegate = mytf_delegate()
      
          c.container_view.frame = (0, 0, 400, 130)
          c.container_view.present('sheet')
          c.container_view.wait_modal()
          # Get rid of the view to avoid a retain cycle:
          c.container_view = None
          if c.was_canceled:
            set_color(1,0,0)
            print('! ', end='')
            set_color()
            print('Cancelled')
            return None
          else:
            try:
              #print(c.values['Fahrenheit:'])
              float(c.values['Fahrenheit:'])
              set_color(0,0,1)	# not 1,1,1 because background is also white 
              print(round((int(c.values['Fahrenheit:'])-32)*5/9,2), end='')
              set_color()
              print('˚C')
            except Exception as e:
              print(e)
              set_color(1,0,0)
              print('! ', end='')
              set_color()
            return c.values
          
      fields = [{'title':'Fahrenheit:','type':'text','value':''}]
      f = myform_dialog(title='dialog title', done_button_title='ok',fields=fields, sections=None) 
      
      1 Reply Last reply Reply Quote 0
      • cvp
        cvp @boegh last edited by cvp

        @boegh this is even better/shorter because in the standard _FormDialogController, delegate is self, thus overriding the textfield_did_end_editing delegate can be set to the done_action even if their (unused) parameter TextField or sender are different but here unused.
        Complex thinking but easy solution. Complex? Ok, I've exaggerated 😀

        import ui
        import dialogs
        from console import set_color
        
        def myform_dialog(title='', fields=None,sections=None, done_button_title='ok'):
            global c
        
            sections = [('', fields)]
            c = dialogs._FormDialogController(title, sections, done_button_title=done_button_title)
            c.textfield_did_end_editing = c.done_action
        
            c.container_view.frame = (0, 0, 400, 130)
            c.container_view.present('sheet')
            c.container_view.wait_modal()
            # Get rid of the view to avoid a retain cycle:
            c.container_view = None
            if c.was_canceled:
              set_color(1,0,0)
              print('! ', end='')
              set_color()
              print('Cancelled')
              return None
            else:
              try:
                #print(c.values['Fahrenheit:'])
                float(c.values['Fahrenheit:'])
                set_color(0,0,1)	# not 1,1,1 because background is also white 
                print(round((int(c.values['Fahrenheit:'])-32)*5/9,2), end='')
                set_color()
                print('˚C')
              except Exception as e:
                print(e)
                set_color(1,0,0)
                print('! ', end='')
                set_color()
              return c.values
            
        fields = [{'title':'Fahrenheit:','type':'text','value':''}]
        f = myform_dialog(title='dialog title', done_button_title='ok',fields=fields, sections=None) 
        
        boegh 1 Reply Last reply Reply Quote 1
        • boegh
          boegh @cvp last edited by

          @cvp, thank you for your quick response.

          I see the magic lies in utilising c.textfield_did_end_editing and assigning that to a done_action(or like) function.

          Again thank you - can I buy you a cup of coffee?

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

            @boegh it's very nice of you, I did not know buymeacoffee.com and it sounds nice, but it is certain that I do not deserve anything for my (always quick and dirty) posts.

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

              Just for the fun...
              I never thought about it before but there is a way to change the frame of the dialog (and define the return as the done button) without redefining the form_dialog.
              You just have to monkey patch the init method of the _FormDialogController class.
              The only problem is that, during a rerun, you have to delete the import of dialogs, otherwise a problem of recurrence occurs.
              Try this, if you want 😀

              import ui
              from console import set_color
              try:
              	del sys.modules['dialogs']
              except:
              	pass
              import dialogs
              original__init__ = dialogs._FormDialogController.__init__	
              def my__init__(self, *args, **kwargs):
              	original__init__(self, *args, **kwargs)
              	self.container_view.frame = (0, 0, 400, 130)
              	self.textfield_did_end_editing = self.done_action
              dialogs._FormDialogController.__init__ = my__init__
              
              fields = [{'title':'Fahrenheit:','type':'text','value':''}]
              f = dialogs.form_dialog(title='dialog title', done_button_title='ok',fields=fields, sections=None)
              if f:
              	try:
              		float(f['Fahrenheit:'])
              		set_color(0,0,1)	# not 1,1,1 because background is also white 
              		print(round((int(f['Fahrenheit:'])-32)*5/9,2), end='')
              		set_color()
              		print('˚C')
              	except Exception as e:
              		print(e)
              		set_color(1,0,0)
              		print('! ', end='')
              		set_color()
              else:
              	set_color(1,0,0)
              	print('! ', end='')
              	set_color()
              	print('Cancelled')
              

              I would like to add that I am proud of myself for having found this, because, sincerely, I am far from mastering Python 😢

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

                Again thank you for the teaching points @cvp :)

                I tried your code, and as you suggested, the rerun did give an error:

                Traceback (most recent call last):
                  File "/private/var/mobile/Containers/Shared/AppGroup/60EBD24F-667F-4F6E-B595-9100C20FC784/Pythonista3/Documents/dialogs_2.py", line 16, in     <module>
                    f = dialogs.form_dialog(title='dialog title', done_button_title='ok',fields=fields, sections=None)
                  File "/var/containers/Bundle/Application/CD376C3C-8193-4F37-B990-A9B960D30F2D/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/site-packages/dialogs.py", line 456, in form_dialog
                    c = _FormDialogController(title, sections, done_button_title=done_button_title)
                  File "/private/var/mobile/Containers/Shared/AppGroup/60EBD24F-667F-4F6E-B595-9100C20FC784/Pythonista3/Documents/dialogs_2.py", line 10, in my__init__
                    original__init__(self, *args, **kwargs)
                  File "/private/var/mobile/Containers/Shared/AppGroup/60EBD24F-667F-4F6E-B595-9100C20FC784/Pythonista3/Documents/dialogs_2.py", line 10, in my__init__
                    original__init__(self, *args, **kwargs)
                  File "/private/var/mobile/Containers/Shared/AppGroup/60EBD24F-667F-4F6E-B595-9100C20FC784/Pythonista3/Documents/dialogs_2.py", line 10, in my__init__
                    original__init__(self, *args, **kwargs)
                  [Previous line repeated 494 more times]
                RecursionError: maximum recursion depth exceeded while calling a Python object
                

                Am I missing something here or isn't it the purpose of the del sys.modules['dialogs']-statement to avoid this issue?

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

                  @boegh said:

                  Am I missing something here or isn't it the purpose of the del sys.modules['dialogs']-statement to avoid this issue?

                  Normally, it is the purpose of deleting the imported dialogs module, did you remove this part of code?

                  I retried my code and it works

                  1 Reply Last reply Reply Quote 0
                  • boegh
                    boegh last edited by boegh

                    @cvp said:

                    Normally, it is the purpose of deleting the imported dialogs module, did you remove this part of code?

                    No I kept it exactly as you wrote it (copy/paste). I can offer no explanation, but I did narrow in on the problem:

                    Removing the try/except-block around the del sys.modules['dialogs']-line, gave me the following error:

                    Traceback (most recent call last):
                      File "/private/var/mobile/Containers/Shared/AppGroup/60EBD24F-667F-4F6E-B595-9100C20FC784/Pythonista3/Documents/dialogs_2.py", line 4, in <module>
                        del sys.modules['dialogs']
                    NameError: name 'sys' is not defined
                    

                    So I tried to add import sys in the beginning of the file, and it worked well. I am a bit perplexed by this behaviour, as I understood it so, that the sys-module would always be loaded?

                    Keeping the import-statement in place, I reinserted the try/except-block and it works flawlessly.

                    I am using Python 3.6 Interpreter in Pythoniste v.3.2 (320000).

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

                      @boegh Strange because, for me, my script runs perfectly several times...
                      Hoping a Python guru would explain us...

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

                        @boegh I think that you are right, you need to import sys to allow correct working of the del.
                        In my case, my pythonista_startup imports it thus its is already imported before my script.

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