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.


    [Idea] Data Entry not using a ui.TableView or dialogs

    Pythonista
    dialogs tableview idea
    2
    4
    3068
    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.
    • Phuket2
      Phuket2 last edited by

      This has probably done before, cant remnber seeing it though. But the code below is just using a view with a repeating number of labels and textfields to collect some data. What I have done is pretty crappy, but it does illustrate a different idea from using the dialogs module or a tableview to collect data. The difficulty to move away from them is the flexibility they offer thats built in. But this approach in my mind could be ok if you had modest needs. Hmmm, maybe. As I say It's just an idea.
      Look many things are missing from this idea, like a scrolling view.
      Maybe this type of an idea would be better moved in to a class. Maybe it should be disregarded altogether. I just wanted to try it out!

      import ui
      
      
      def text_form(items=None, width=320, **kwargs):
          if not items or not len(items):
              raise ValueError('items needs to be a list of strings or dicts')
      
          global _results
          input_flds = []
          _results = None
          _current_y = 6
          _gap = 6
      
          v = ui.View(frame=(0, 0, width, 100), **kwargs)
      
          def obj_kwargs_setter(obj, **kwargs):
              '''
              generic way to set the kwargs for a given object
              '''
              [setattr(obj, k, v) for k, v in kwargs.items() if hasattr(obj, k)]
      
          def _collect_data(sender):
              '''
              collect the data in the textfields
              '''
              global _results
              _results = [{'key': obj.key, 'value': obj.text} for obj in input_flds]
              sender.superview.close()
      
          def _cancel_action(sender):
              sender.superview.close()
      
          def make_btn(name, title, action=None, **kwargs):
              '''
              create what I think is a std btn.  kwargs will overwite any attr
              '''
              btn = ui.Button(height=32,
                              name=name,
                              title=title,
                              border_width=.5,
                              border_color='black',
                              bg_color='white',
                              corner_radius=6,
                              action=action,
                              )
              btn.width = 80
              obj_kwargs_setter(btn, **kwargs)
              return btn
      
          def make_field(fld_dict, y, **kwargs):
              '''
              create what I think is a std label + textField.
              kwargs will overwite any attr of the textfield
              '''
              current_y = y
              lb = ui.Label(frame=(6, current_y, 100, 32),
                            text=str(fld_dict['title']),
                            name=str(fld_dict['title']),
                            )
      
              fld = ui.TextField(frame=(82, current_y, 230, 32))
              fld.key = fld_dict['key']
              input_flds.append(fld)
              obj_kwargs_setter(fld, **kwargs)
              v.add_subview(lb)
              v.add_subview(fld)
              return fld.height + _gap
      
          flds = []
          '''
          step 1. checking to see if we have a list of strings or dicts.
          hmmm, only checking the first element :(
          This is imcomplete, just looking at a list of str's at the moment,
          but still creating dict items. Although they are still not finished yet
          '''
          if isinstance(items[0], str):
              for l in items:
                  flds.append(dict(type='Text', key=l, value='', title=l))
          elif isinstance(items[0], dict):
              '''
              Not implemented yet
              '''
              pass
      
          # make the labels & fields
          for fld in flds:
              y = make_field(fld, _current_y)
              _current_y += y
      
          # make & position the ok and canel buttons
          ok_btn = make_btn('ok', 'OK', bg_color='purple', action=_collect_data,
                            tint_color='white')
          v.add_subview(ok_btn)
      
          cancel_btn = make_btn('cancel', 'Cancel', _cancel_action,
                                bg_color='deeppink', tint_color='white')
          v.add_subview(cancel_btn)
      
          ok_btn.y = _current_y + _gap
          ok_btn.x = v.frame.max_x - (ok_btn.width + _gap)
          _current_y += ok_btn.height + _gap
      
          cancel_btn.y = ok_btn.y
          cancel_btn.x = ok_btn.frame.min_x - (ok_btn.width + _gap)
      
          v.height = _current_y + _gap
      
          # make the first field ready for input, without having to tap it
          input_flds[0].begin_editing()
      
          v.present('sheet', animated=False)
          v.wait_modal()
          return _results
      
      if __name__ == '__main__':
          results = text_form(['Service', 'Account', 'Password'], bg_color='white',
                              name='Add KeyChain Service')
          #results = text_form(['First', 'Last', 'Age', 'email'], bg_color='white',
                              #name='Add Person')
      
          print(results)
      
      1 Reply Last reply Reply Quote 0
      • cvp
        cvp last edited by

        Why, in make_btn of ok, do you need action=... and in make_btn of cancel, not?

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

          @cvp , it was inconsistency poor on my part. action is an *arg, so its being accepted as a named *arg or a positional arg.
          To be consistent i should have done :

          cancel_btn = make_btn('cancel', 'Cancel',action=_cancel_action,
                                    bg_color='deeppink', tint_color='white')
          

          or left out the action specifier altogether in both calls, as they are positional arguments.

          ok_btn = make_btn('ok', 'OK', bg_color='purple', action=_collect_data,
          tint_color='white')
          cancel_btn = make_btn('cancel', 'Cancel', action=_cancel_action,
          bg_color='deeppink', tint_color='white')

          ok_btn = make_btn('ok', 'OK', bg_color='purple', _collect_data,
          tint_color='white')
          cancel_btn = make_btn('cancel', 'Cancel', _cancel_action,
          bg_color='deeppink', tint_color='white')

          Its not clear but should be equivalent,
          1 Reply Last reply Reply Quote 0
          • cvp
            cvp last edited by

            Thanks for your explanation, I didn't know this *arg, but, really, what do I know?
            Surely, not a lot 😭

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