omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular
    1. Home
    2. RoninSage

    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.


    • Profile
    • Following 0
    • Followers 0
    • Topics 2
    • Posts 11
    • Best 0
    • Controversial 0
    • Groups 0

    RoninSage

    @RoninSage

    0
    Reputation
    513
    Profile views
    11
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    RoninSage Unfollow Follow

    Latest posts made by RoninSage

    • RE: Changing button shape using up.Path

      @brumm thanks, just enough info for me to figure it out.

      posted in Pythonista
      RoninSage
      RoninSage
    • RE: Changing button shape using up.Path

      @enceladus That last code worked, just a quick question, if I wanted a second button, is there an easy way to do that?

      posted in Pythonista
      RoninSage
      RoninSage
    • RE: Changing button shape using up.Path

      @brumm thanks for the help but the code In the link did not work when I tried to run it.

      @enceladus this is a start but the button still exists as a rectangle around the hexagon picture. Any tips to make sure that only tapping the shape will activate the button?

      posted in Pythonista
      RoninSage
      RoninSage
    • Changing button shape using up.Path

      I want to have a button that has a different shape than a rectangle. I think ui.Path is the way to go but I am having trouble implementing it. I have code for a simple button press. Could I get some help changing it so the button changes to say a hexagon?

      
      import ui
      # Define variables
      btn_counter=-1 # button pressed count
      btn_color=['red','magenta','blue','green','yellow','cyan'] # button colours
      btn_txt=['click again','click one more time','have another go','go again please', 'one last press','finally'] # button text when pressed
      # Define functions
      # What button1 does when tapped
      def button1_tapped(sender):
        global btn_counter # count number of times the button is pressed
        btn_counter+=1
        if btn_counter<=5: # cycle through button colours
          sender.title = btn_txt[btn_counter] # change button text when pressed
          sender.size_to_fit() # adjust button size to fit new text exactly
          button1.width=1.5*button1.width # change button width
          button1.height=2*button1.height # change button height
          button1.bg_color = btn_color[btn_counter] # change button colour when tapped
        else:
          view.remove_subview(button1) # remove button
          some_box.title = 'thank you for your time' # change box text
          some_box.size_to_fit() # change box size to fit new text exactly
          some_box.frame=(view.width*0.38,view.height*0.45,1.1*some_box.width,2*some_box.height) # change box location and size
      
      # Create display, further details see theBackground.py
      view=ui.View()
      view.present('fullscreen', hide_title_bar=True)
      view.background_color = (214/255,12/255,140/255)
      
      # Create button
      button1 = ui.Button(title='Click me') # initial button text
      button1.center = (view.width*0.38, view.height*0.45) # Button initial position
      button1.border_width = 5 # give button a border
      #button1.size_to_fit() # fit button around text exactly
      button1.width = view.width*0.3 # button width
      button1.height = view.height*0.2 # button height
      button1.bg_color = (.3,.31,.32) # button colour (.3,.31,.32,0) fof transparent
      button1.font = ('Chalkduster', 30) # button font type and size
      button1.tint_color=(1,1,1) # button font colour
      button1.action = button1_tapped # needed for when button pressed
      view.add_subview(button1) # display button
      
      # Include non-interactive box
      some_box = ui.Label(
        text='This is not a button', # box text
        background_color=(95/255,96/255,98/255), # box colour
        text_color='white', # box text colour
        alignment=ui.ALIGN_CENTER, # text alignment in box
        number_of_lines=0, # number of lines used in box
        frame=(10, 10, view.width-20, 100)) # box position (10 in, 10 down, view.width-20 wide, 100 high)
      some_box.font=('HoeflerText-BlackItalic', 40) # box font type and size
      view.add_subview(some_box) # show box
      
      
      posted in Pythonista
      RoninSage
      RoninSage
    • RE: Interactive test

      @cvp perfect, that simplified all the repetions and I still understand what is going on, thanks heaps.

      posted in Pythonista
      RoninSage
      RoninSage
    • RE: Interactive test

      I have created code that works and does what I want it to do, however, I feel like there is a more condensed way to do this. By creating my own keyboard I can limit the inputs that are available, I can also stop that annoying little bar coming up at the bottom of the screen.

      Below the comment

      # functions that define key button actions

      I feel there is a lot of repetition that could be done more efficiently. Also, below the comment

      # Create key buttons

      again, there is also a lot of repetition. I am sure there is a simple iterative way to approach this, but I am at a loss as to how to do it.

      Thanks for you help.

      
      import ui, itertools
      import numpy as np
      from objc_util import *
      
      # Define variables
      # Create display, further details see theBackground.py
      view=ui.View()
      view.present('fullscreen', hide_title_bar=True)
      view.background_color = ('lightgreen')
      answers=[]
      
      # Counters
      ent_count=0
      
      # Define functions
      # function that allows you to define font as a number using font_list[]
      def get_font_list():
        UIFont = ObjCClass('UIFont')
        return list(itertools.chain(*[UIFont.fontNamesForFamilyName_(str(x))
              for x in UIFont.familyNames()]))
      font_list = get_font_list()
      for i in range(len(font_list)):
        font_list[i]=str(font_list[i])
      
      # function that adds all keys to the screen
      def add_keyboard1(some_list):
        for key in some_list:
          view.add_subview(some_list[key])
      
      # function that removes all keys from the screen
      def remove_keyboard1(some_list):
        for key in range(0,len(some_list)):
          view.remove_subview(some_list[key])
      
      # function to create key buttons
      def create_btn(btn_label,btn_name,btn_x,btn_y,btn_width):
        btn_name.bg_color = (95/255,96/255,98/255,0.8) # button colour
        btn_name.tint_color=(141/255,198/255,63/255) # button font colour
        btn_name.center = (btn_x+view.width*0.215, btn_y-view.height*0.1) # button position
        btn_name.border_width = .5 # add border to button
        btn_name.width = btn_width # button width
        btn_name.height = view.width*0.04 # button height
        btn_name.font = (font_list[7], 20) # button font type and size
        btn_name.corner_radius = view.width * 0.002 # rounds button corners
        view.add_subview(btn_name) # draw button
      
      # functions that define key button actions
      def btn1_tap(sender):
        txt_fld.text=txt_fld.text +'1'
      def btn2_tap(sender):
        txt_fld.text=txt_fld.text +'2'
      def btn3_tap(sender):
        txt_fld.text=txt_fld.text +'3'
      def btn4_tap(sender):
        txt_fld.text=txt_fld.text +'4'
      def btn5_tap(sender):
        txt_fld.text=txt_fld.text +'5'
      def btn6_tap(sender):
        txt_fld.text=txt_fld.text +'6'
      def btn7_tap(sender):
        txt_fld.text=txt_fld.text +'7'
      def btn8_tap(sender):
        txt_fld.text=txt_fld.text +'8'
      def btn9_tap(sender):
        txt_fld.text=txt_fld.text +'9'
      def btn0_tap(sender):
        txt_fld.text=txt_fld.text +'0'
      def btndel_tap(sender):
        txt_fld.text=txt_fld.text[:-1]
      def btnq_tap(sender):
        txt_fld.text=txt_fld.text +'q'
      def btnw_tap(sender):
        txt_fld.text=txt_fld.text +'w'
      def btne_tap(sender):
        txt_fld.text=txt_fld.text +'e'
      def btnr_tap(sender):
        txt_fld.text=txt_fld.text +'r'
      def btnt_tap(sender):
        txt_fld.text=txt_fld.text +'t'
      def btny_tap(sender):
        txt_fld.text=txt_fld.text +'y'
      def btnu_tap(sender):
        txt_fld.text=txt_fld.text +'u'
      def btni_tap(sender):
        txt_fld.text=txt_fld.text +'i'
      def btno_tap(sender):
        txt_fld.text=txt_fld.text +'o'
      def btnp_tap(sender):
        txt_fld.text=txt_fld.text +'p'
      def btnsf_tap(sender):
        txt_fld.text=txt_fld.text +'๐Ÿ™'
      def btna_tap(sender):
        txt_fld.text=txt_fld.text +'a'
      def btns_tap(sender):
        txt_fld.text=txt_fld.text +'s'
      def btnd_tap(sender):
        txt_fld.text=txt_fld.text +'d'
      def btnf_tap(sender):
        txt_fld.text=txt_fld.text +'f'
      def btng_tap(sender):
        txt_fld.text=txt_fld.text +'g'
      def btnh_tap(sender):
        txt_fld.text=txt_fld.text +'h'
      def btnj_tap(sender):
        txt_fld.text=txt_fld.text +'j'
      def btnk_tap(sender):
        txt_fld.text=txt_fld.text +'k'
      def btnl_tap(sender):
        txt_fld.text=txt_fld.text +'l'
      def btnhf_tap(sender):
        txt_fld.text=txt_fld.text +'๐Ÿ™‚'
      def btnz_tap(sender):
        txt_fld.text=txt_fld.text +'z'
      def btnx_tap(sender):
        txt_fld.text=txt_fld.text +'x'
      def btnc_tap(sender):
        txt_fld.text=txt_fld.text +'c'
      def btnv_tap(sender):
        txt_fld.text=txt_fld.text +'v'
      def btnb_tap(sender):
        txt_fld.text=txt_fld.text +'b'
      def btnn_tap(sender):
        txt_fld.text=txt_fld.text +'n'
      def btnm_tap(sender):
        txt_fld.text=txt_fld.text +'m'
      def btnm_tap(sender):
        txt_fld.text=txt_fld.text +'m'
      def btnenter_tap(sender):
        global ent_count
        if len(txt_fld.text)!=0:
          ent_count+=1
          if ent_count<3: # after 3rd entry stops input
            answers.append(txt_fld.text) # records all inputs
            txt_fld.text='' # clears entry after enter is pressed
          else:
            answers.append(txt_fld.text) # records last input
            view.remove_subview(txt_fld) # clears textfield
            some_box.text='My time is a valuable thing' # changes box text
            remove_keyboard1(all_btns) # clears all keys
            view.close()
      
      # Create key buttons
      btn1 = ui.Button(title='1')
      create_btn('1',btn1,view.width*0.0,view.height*0.66,view.width*0.04)
      btn1.action = btn1_tap
      btn2 = ui.Button(title='2')
      create_btn('2',btn2,view.width*0.05,view.height*0.66,view.width*0.04)
      btn2.action = btn2_tap
      btn3 = ui.Button(title='3')
      create_btn('3',btn3,view.width*0.1,view.height*0.66,view.width*0.04)
      btn3.action = btn3_tap
      btn4 = ui.Button(title='4')
      create_btn('4',btn4,view.width*0.15,view.height*0.66,view.width*0.04)
      btn4.action = btn4_tap
      btn5 = ui.Button(title='5')
      create_btn('5',btn5,view.width*0.2,view.height*0.66,view.width*0.04)
      btn5.action = btn5_tap
      btn6 = ui.Button(title='6')
      create_btn('6',btn6,view.width*0.25,view.height*0.66,view.width*0.04)
      btn6.action = btn6_tap
      btn7 = ui.Button(title='7')
      create_btn('7',btn7,view.width*0.3,view.height*0.66,view.width*0.04)
      btn7.action = btn7_tap
      btn8 = ui.Button(title='8')
      create_btn('8',btn8,view.width*0.35,view.height*0.66,view.width*0.04)
      btn8.action = btn8_tap
      btn9 = ui.Button(title='9')
      create_btn('9',btn9,view.width*0.4,view.height*0.66,view.width*0.04)
      btn9.action = btn9_tap
      btn0 = ui.Button(title='0')
      create_btn('0',btn0,view.width*0.45,view.height*0.66,view.width*0.04)
      btn0.action = btn0_tap
      btndel = ui.Button(title='delete')
      create_btn('delete',btndel,view.width*0.505,view.height*0.66,view.width*0.09)
      btndel.action = btndel_tap
      btnq = ui.Button(title='q')
      create_btn('q',btnq,view.width*0.025,view.height*0.73,view.width*0.04)
      btnq.action = btnq_tap
      btnw = ui.Button(title='w')
      create_btn('w',btnw,view.width*0.075,view.height*0.73,view.width*0.04)
      btnw.action = btnw_tap
      btne = ui.Button(title='e')
      create_btn('e',btne,view.width*0.125,view.height*0.73,view.width*0.04)
      btne.action = btne_tap
      btnr = ui.Button(title='r')
      create_btn('r',btnr,view.width*0.175,view.height*0.73,view.width*0.04)
      btnr.action = btnr_tap
      btnt = ui.Button(title='t')
      create_btn('t',btnt,view.width*0.225,view.height*0.73,view.width*0.04)
      btnt.action = btnt_tap
      btny = ui.Button(title='y')
      create_btn('y',btny,view.width*0.275,view.height*0.73,view.width*0.04)
      btny.action = btny_tap
      btnu = ui.Button(title='u')
      create_btn('u',btnu,view.width*0.325,view.height*0.73,view.width*0.04)
      btnu.action = btnu_tap
      btni = ui.Button(title='i')
      create_btn('i',btni,view.width*0.375,view.height*0.73,view.width*0.04)
      btni.action = btni_tap
      btno = ui.Button(title='o')
      create_btn('o',btno,view.width*0.425,view.height*0.73,view.width*0.04)
      btno.action = btno_tap
      btnp = ui.Button(title='p')
      create_btn('p',btnp,view.width*0.475,view.height*0.73,view.width*0.04)
      btnp.action = btnp_tap
      btnsf = ui.Button(title='๐Ÿ™')
      create_btn('๐Ÿ™',btnsf,view.width*0.525,view.height*0.73,view.width*0.04)
      btnsf.action = btnsf_tap
      btna = ui.Button(title='a')
      create_btn('a',btna,view.width*0.05,view.height*0.8,view.width*0.04)
      btna.action = btna_tap
      btns = ui.Button(title='s')
      create_btn('s',btns,view.width*0.1,view.height*0.8,view.width*0.04)
      btns.action = btns_tap
      btnd = ui.Button(title='d')
      create_btn('d',btnd,view.width*0.15,view.height*0.8,view.width*0.04)
      btnd.action = btnd_tap
      btnf = ui.Button(title='f')
      create_btn('f',btnf,view.width*0.2,view.height*0.8,view.width*0.04)
      btnf.action = btnf_tap
      btng = ui.Button(title='g')
      create_btn('g',btng,view.width*0.25,view.height*0.8,view.width*0.04)
      btng.action = btng_tap
      btnh = ui.Button(title='h')
      create_btn('h',btnh,view.width*0.3,view.height*0.8,view.width*0.04)
      btnh.action = btnh_tap
      btnj = ui.Button(title='j')
      create_btn('j',btnj,view.width*0.35,view.height*0.8,view.width*0.04)
      btnj.action = btnj_tap
      btnk = ui.Button(title='k')
      create_btn('k',btnk,view.width*0.4,view.height*0.8,view.width*0.04)
      btnk.action = btnk_tap
      btnl = ui.Button(title='l')
      create_btn('l',btnl,view.width*0.45,view.height*0.8,view.width*0.04)
      btnl.action = btnl_tap
      btnhf = ui.Button(title='๐Ÿ™‚')
      create_btn('๐Ÿ™‚',btnhf,view.width*0.5,view.height*0.8,view.width*0.04)
      btnhf.action = btnhf_tap
      btnz = ui.Button(title='z')
      create_btn('z',btnz,view.width*0.075,view.height*0.87,view.width*0.04)
      btnz.action = btnz_tap
      btnx = ui.Button(title='x')
      create_btn('x',btnx,view.width*0.125,view.height*0.87,view.width*0.04)
      btnx.action = btnx_tap
      btnc = ui.Button(title='c')
      create_btn('c',btnc,view.width*0.175,view.height*0.87,view.width*0.04)
      btnc.action = btnc_tap
      btnv = ui.Button(title='v')
      create_btn('v',btnv,view.width*0.225,view.height*0.87,view.width*0.04)
      btnv.action = btnv_tap
      btnb = ui.Button(title='b')
      create_btn('b',btnb,view.width*0.275,view.height*0.87,view.width*0.04)
      btnb.action = btnb_tap
      btnn = ui.Button(title='n')
      create_btn('n',btnn,view.width*0.325,view.height*0.87,view.width*0.04)
      btnn.action = btnn_tap
      btnm = ui.Button(title='m')
      create_btn('m',btnm,view.width*0.375,view.height*0.87,view.width*0.04)
      btnm.action = btnm_tap
      btnenter = ui.Button(title='enter')
      create_btn('enter',btnenter,view.width*0.425,view.height*0.87,view.width*0.09)
      btnenter.action = btnenter_tap
      
      # List of all button names
      all_btns=(btn1,btn2,btn3,btn4,btn5,btn6,btn7,btn8,btn9,btn0,btndel,
      btnq,btnw,btne,btnr,btnt,btny,btnu,btni,btno,btnp,btnsf,
      btna,btns,btnd,btnf,btng,btnh,btnj,btnk,btnl,btnhf,
      btnz,btnx,btnc,btnv,btnb,btnn,btnm,btnenter)
      
      # Include non-interactive box
      some_box = ui.Label(
        text='This is where you can ask some questions', # box text
        background_color=(95/255,96/255,98/255), # box colour
        text_color='white', # box text colour
        alignment=ui.ALIGN_CENTER, # text alignment in box
        number_of_lines=0, # number of lines used in box
        frame=(0, 0, view.width, 100)) # position of top box (0 in, 0 down, view.width wide, 100 high)
      some_box.font=('HoeflerText-BlackItalic', 40) # box font type and size
      view.add_subview(some_box) # create box
      
      txt_fld=ui.TextField(frame=(view.width*0.275, view.height*0.34,view.width*0.45, view.height*0.1)) # defines textfield dimensions
      txt_fld.alignment=ui.ALIGN_CENTER # places text in center of the box
      txt_fld.font = ('Chalkduster', 30) # change textfield font
      txt_fld.text_color='hotpink' # text colour
      txt_fld.enabled = False # cannot click in textfield
      view.add_subview(txt_fld) # create textfield
      
      
      posted in Pythonista
      RoninSage
      RoninSage
    • RE: Interactive test

      @enceladus & @ellie_ff1493 thanks for the suggestions but it is not really where I wanted to go with this. Below is code that is starting to get there, however, I want all of the question boxes to move onto the next question whenever one of them is selected. I am sure how to do that. Also, I have included code at the bottom that will record the answers selected into a csv file for later use, I just need help with the code that records the selections into a list. Finally, to complete everything, I would like to start the test off with the participant entering Name, Surname, phone number and email, again something I havenโ€™t figured out yet but I am guessing will need access to the soft keyboard. The code probably needs some cleaning up as I just started working with the code that @cvp linked to earlier.

      
      import itertools, ui, uuid
      from objc_util import *
      
      # Generate list of all fonts
      def get_font_list():
        UIFont = ObjCClass('UIFont')
        return list(itertools.chain(*[UIFont.fontNamesForFamilyName_(str(x))
              for x in UIFont.familyNames()]))
      font_list = get_font_list()
      for i in range(len(font_list)):
        font_list[i]=str(font_list[i])
      
      UILayoutContainerView = ObjCClass('UILayoutContainerView')
      UISwipeGestureRecognizer = ObjCClass('UISwipeGestureRecognizer')
      
      def disable_swipe_to_close(view):
        v = view.objc_instance
        while not v.isKindOfClass_(UILayoutContainerView.ptr):
          v = v.superview()
        for gr in v.gestureRecognizers():
          if gr.isKindOfClass_(UISwipeGestureRecognizer.ptr):
            gr.setEnabled(False)
      
      class Gestures():
      
        TYPE_REGULAR = 0
        TYPE_FORCE = 1
        TYPE_STYLUS = 4
        TYPE_ANY = 8. 
      
        TAP = b'UITapGestureRecognizer'
        PINCH = b'UIPinchGestureRecognizer'
        ROTATION = b'UIRotationGestureRecognizer'
        SWIPE = b'UISwipeGestureRecognizer'
        PAN = b'UIPanGestureRecognizer'
        SCREEN_EDGE_PAN = b'UIScreenEdgePanGestureRecognizer'
        LONG_PRESS = b'UILongPressGestureRecognizer'
      
        CHANGED = 2
        ENDED = 3
      
        RIGHT = 1; LEFT = 2; UP = 4; DOWN = 8
      
        EDGE_NONE = 0; EDGE_TOP = 1; EDGE_LEFT = 2; EDGE_BOTTOM = 4; EDGE_RIGHT = 8; EDGE_ALL = 15
      
        def __init__(self, touch_type=TYPE_REGULAR, force_threshold=0.4, retain_global_reference = True):
          self.buttons = {}
          self.views = {}
          self.recognizers = {}
          self.actions = {}
          self.touches = {}
          self.touch_type = touch_type
          self.force_threshold = force_threshold
          if retain_global_reference:
            retain_global(self)
      
          # Friendly delegate functions
      
          def recognize_simultaneously_default(gr_name, other_gr_name):
            return False    
          self.recognize_simultaneously = recognize_simultaneously_default
          
          def fail_default(gr_name, other_gr_name):
            return False    
          self.fail = fail_default
          
          def fail_other_default(gr_name, other_gr_name):
            return False    
          self.fail_other = fail_other_default
      
          # ObjC delegate functions
          
          def simplify(func, gr, other_gr):
            gr_o = ObjCInstance(gr)
            other_gr_o = ObjCInstance(other_gr)
            if (gr_o.view() != other_gr_o.view()):
              return False
            gr_name = gr_o._get_objc_classname()
            other_gr_name = other_gr_o._get_objc_classname()
            return func(gr_name, other_gr_name)
          
          # Recognize simultaneously
      
          def gestureRecognizer_shouldRecognizeSimultaneouslyWithGestureRecognizer_(_self, _sel, gr, other_gr):
            return self.objc_should_recognize_simultaneously(self.recognize_simultaneously, gr, other_gr)
      
          def objc_should_recognize_simultaneously_default(func, gr, other_gr):
            return simplify(func, gr, other_gr)
            
          self.objc_should_recognize_simultaneously = objc_should_recognize_simultaneously_default
          
          # Fail other
          
          def gestureRecognizer_shouldRequireFailureOfGestureRecognizer_(_self, _sel, gr, other_gr):
            return self.objc_should_require_failure(self.fail_other, gr, other_gr)
      
          def objc_should_require_failure_default(func, gr, other_gr):
            return simplify(func, gr, other_gr)
            
          self.objc_should_require_failure = objc_should_require_failure_default
          
          # Fail
          
          def gestureRecognizer_shouldBeRequiredToFailByGestureRecognizer_(_self, _sel, gr, other_gr):
            return self.objc_should_fail(self.fail, gr, other_gr)
      
          def objc_should_fail_default(func, gr, other_gr):
            return simplify(func, gr, other_gr)
            
          self.objc_should_fail = objc_should_fail_default
          
          # Delegate
          
          try:
            PythonistaGestureDelegate = ObjCClass('PythonistaGestureDelegate')
          except:
            PythonistaGestureDelegate = create_objc_class('PythonistaGestureDelegate',
            superclass=NSObject,
            methods=[
              gestureRecognizer_shouldRecognizeSimultaneouslyWithGestureRecognizer_,
              gestureRecognizer_shouldRequireFailureOfGestureRecognizer_,
              gestureRecognizer_shouldBeRequiredToFailByGestureRecognizer_],
            classmethods=[],
            protocols=['UIGestureRecognizerDelegate'],
            debug=True)
          self._delegate = PythonistaGestureDelegate.new()
      
        @on_main_thread
        def add_tap(self, view, action, number_of_taps_required = None, number_of_touches_required = None):
          ''' Call `action` when a tap gesture is recognized for the `view`.
          
          Additional parameters:
            
          * `number_of_taps_required` - Set if more than one tap is required for the gesture to be recognized.
          * `number_of_touches_required` - Set if more than one finger is required for the gesture to be recognized.
          '''
          recog = self._get_recog('UITapGestureRecognizer', view, self._general_action, action)
      
          if number_of_taps_required:
            recog.numberOfTapsRequired = number_of_taps_required
          if number_of_touches_required:
            recog.numberOfTouchesRequired = number_of_touches_required
          return recog
      
        @on_main_thread
        def add_screen_edge_pan(self, view, action, edges):
          ''' Call `action` when a pan gesture starting from the edge is recognized for the `view`. This is a continuous gesture.
          
          `edges` must be set to one of `Gestures.EDGE_NONE/EDGE_TOP/EDGE_LEFT/EDGE_BOTTOM/EDGE_RIGHT/EDGE_ALL`. If you want to recognize pans from different edges, you have to set up separate recognizers with separate calls to this method.
          
          Handler `action` receives the same gesture-specific attributes in the `data` argument as pan gestures, see `add_pan`.
          '''
          recog = self._get_recog('UIScreenEdgePanGestureRecognizer', view, self._pan_action, action)
      
          recog.edges = edges
      
          return recog
      
        def _get_recog(self, recog_name, view, internal_action, final_handler):
          view.touch_enabled = True
          button = ui.Button()
          key = str(uuid.uuid4())
          button.name = key
          button.action = internal_action
          self.buttons[key] = button
          self.views[key] = view
          recognizer = ObjCClass(recog_name).alloc().initWithTarget_action_(button, sel('invokeAction:')).autorelease()
          self.recognizers[key] = recognizer
          self.actions[key] = final_handler
          ObjCInstance(view).addGestureRecognizer_(recognizer)
          recognizer.delegate = self._delegate
          return recognizer
      
        class Data():
          def __init__(self):
            self.recognizer = self.view = self.location = self.state = self.number_of_touches = self.scale = self.rotation = self.velocity = None
      
        def _context(self, button):
          key = button.name
          (view, recog, action) = (self.views[key], self.recognizers[key], self.actions[key])
          data = Gestures.Data()
          data.recognizer = recog
          data.view = view
          data.location = self._location(view, recog)
          data.state = recog.state()
          data.number_of_touches = recog.numberOfTouches()
          #data.additional_touch_data = self.touches[recog]
          return (data, action)
      
        def _location(self, view, recog):
          loc = recog.locationInView_(ObjCInstance(view))
          return ui.Point(loc.x, loc.y)
      
        def _general_action(self, sender):
          (data, action) = self._context(sender)
          action(data)
      
        def _pan_action(self, sender):
          (data, action) = self._context(sender)
          trans = data.recognizer.translationInView_(ObjCInstance(data.view))
          vel = data.recognizer.velocityInView_(ObjCInstance(data.view))
          data.translation = ui.Point(trans.x, trans.y)
          data.velocity = ui.Point(vel.x, vel.y)
      
          action(data)
      
          action(data)
      
      # TESTING AND DEMONSTRATION
      
      if __name__ == "__main__":
        
        import math, random
        
        g = Gestures()
        
        def random_background(view):
          colors = [(0.3,0.31,0.32), (0.25,0.26,0.27), (0.2,0.21,0.22), (0.15,0.16,0.17), (0.35,0.36,0.37), (0.4,0.41,0.42), (0.45,0.46,0.47), (0.5,0.51,0.52)]
          view.background_color = random.choice(colors)
          view.text_color = (0,0,0) if sum(view.background_color[:3]) > 1.5 else (1,1,1) # colour of font after press button
      
        def update_text(l, text):
          l.text = text
      
        q1_count=-1
        def generic_handler1(data):
          random_background(data.view)
          global q1_count
          q1_count+=1
          if q1_count<=len(Questions1)-1:
            update_text(data.view,Questions1[q1_count])
          else:
            update_text(data.view,'done')
      
        q2_count=-1
        def generic_handler2(data):
          random_background(data.view)
          global q2_count
          q2_count+=1
          if q2_count<=len(Questions2)-1:
            update_text(data.view,Questions2[q2_count])
          else:
            update_text(data.view,'done')
      
        q3_count=-1
        def generic_handler3(data):
          random_background(data.view)
          global q3_count
          q3_count+=1
          if q3_count<=len(Questions3)-1:
            update_text(data.view,Questions3[q3_count])
          else:
            update_text(data.view,'done')
      
        q4_count=-1
        def generic_handler4(data):
          random_background(data.view)
          global q4_count
          q4_count+=1
          if q4_count<=len(Questions4)-1:
            update_text(data.view,Questions4[q4_count])
          else:
            update_text(data.view,'done')
      
        def pan_handler(data):
          update_text(data.view, 'done')
          random_background(data.view)
          bg.close()
      
        Questions1=['What are my strengths?','What frustrates me?','What do I prefer to wear?','What does my desk look like?','When making a large purchase I prioritise:','Who inspires you;']
        Questions2=['ohW','nehW','erehW','yhW','tahw','woH']
        Questions3=['1st ?','2nd ?','3rd ?','4th ?','5th ?','6th ?']
        Questions4=['Question 1','Question 2','Question 3','Question 4','Question 5','Question 6']
      
        bg = ui.View()
        bg.present(style='default',hide_title_bar=True,title_bar_color=(198/255,50/255,108/255), title_color='Green')
        disable_swipe_to_close(bg) # Use to limit access to code
        bg.background_color=(198/255,50/255,108/255) # set background color to pink
        edge_l = ui.Label(
          text='Complete as quickly as possible', 
          background_color='grey',
          text_color='white',
          alignment=ui.ALIGN_CENTER,
          number_of_lines=0,
          frame=(
            0, 0, bg.width, 136 # position of top box (0 in, 0 down, bg.width wide, 136 high)
        ))
        edge_l.font=(font_list[71], 40) # font type and size
        bg.add_subview(edge_l)
        g.add_screen_edge_pan(edge_l, pan_handler, edges=Gestures.EDGE_RIGHT)
      
        v = ui.ScrollView(frame=(0, 95, bg.width, bg.height))  # where grid of boxes are placed 
        bg.add_subview(v)
        
        label_count = -1
        
        def create_label(title):
          global label_count
          label_count += 1
          label_w = 443
          label_h = 300
          gap = 120
          label_w_with_gap = label_w + gap
          label_h_with_gap = label_h + gap
          labels_per_line = math.floor((v.width-2*gap)/(label_w+gap))
          left_margin = (v.width - labels_per_line*label_w_with_gap + gap)/2
          line = math.floor(label_count/labels_per_line)
          column = label_count - line*labels_per_line
          
          l = ui.Label(
            text=title, 
            background_color=(95/255,96/255,98/255), # box colour
            text_color=(141/255,198/255,63/255), # text colour
            alignment=ui.ALIGN_CENTER,
            number_of_lines=0,
            frame=(
              left_margin+column * label_w_with_gap,
              gap+line * label_h_with_gap,
              label_w, label_h
          ))
          l.font=(font_list[32], 40) # font type and size
          v.add_subview(l)
          return l
      
        tap_1 = create_label("What is included in your perfect night in? \n \n Nailing a DYI project")
        tap_2 = create_label("What is included in your perfect night in? \n \n Bath, bed and a good book?")
        tap_3 = create_label("What is included in your perfect night in? \n \n Doonah, snacks, movie and someone to cuddle?")
        tap_4 = create_label("What is included in your perfect night in? \n \n It does'nt matter as long as the house is clean!")
        g.add_tap(tap_1, generic_handler1)
        g.add_tap(tap_2, generic_handler2)
        g.add_tap(tap_3, generic_handler3)
        g.add_tap(tap_4, generic_handler4)
      
      # code to export results to csv file once it is the same for as res given below
      import csv
      res = ['x', '2', 4.7]
      csvfile = 'data.csv'
      
      with open(csvfile, "w") as output:
          writer = csv.writer(output, lineterminator='\n')
          for val in res:
              writer.writerow([val])
      
      
      posted in Pythonista
      RoninSage
      RoninSage
    • RE: UI Sheet View, Can you hide the x?

      @mikael perfect, that does exactly what I wanted. Combined with guided access mode on the iPad, once the python program starts to run the user shouldnโ€™t be able to leave the view at all.

      But if anyone wants to use this code, I have edited the button function so it will eventually let you out, unfortunately I am not as elegant as @mikael

      Cheers

      #coding: utf-8
      import ui, random
      from ui import *
      from objc_util import *
      
      
      def button_tapped(sender):
        rn=random.random()
        if rn <0.8:
          sender.title = 'unlucky, click again to close'
          button.size_to_fit
        else:
          view.close()
      
      UILayoutContainerView = ObjCClass('UILayoutContainerView')
      UISwipeGestureRecognizer = ObjCClass('UISwipeGestureRecognizer')
      
      def disable_swipe_to_close(view):
        v = view.objc_instance
        while not v.isKindOfClass_(UILayoutContainerView.ptr):
          v = v.superview()
        for gr in v.gestureRecognizers():
          if gr.isKindOfClass_(UISwipeGestureRecognizer.ptr):
            gr.setEnabled(False)
      
      view = ui.View()
      view.background_color = (0.3,0.31,0.32)
      button = ui.Button(title='Click this button to close view')
      button.center = (view.width * 0.5, view.height * 0.5)
      button.flex = 'LRTB'
      button.action = button_tapped
      view.add_subview(button)
      view.present('fullscreen', hide_title_bar=True)
      disable_swipe_to_close(view)
      
      
      posted in Pythonista
      RoninSage
      RoninSage
    • RE: UI Sheet View, Can you hide the x?

      Is there a way to stop two-finger swipe down gesture from exiting a view with a hidden title bar?

      posted in Pythonista
      RoninSage
      RoninSage
    • RE: Interactive test

      It seemed the best way to use the touch screen interface of the iPad. I am open to other suggestions.

      posted in Pythonista
      RoninSage
      RoninSage