omz:forum

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

    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

    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
    • Interactive test

      I would like to create an interactive quiz using Pythonista. I was trying to learn how to use the scene kit but I was having trouble doing even basic operations based on the limited examples in the documentation. I would like the questions to pop up and to tap the answers. At the end of the test, all the selected answers would be saved to a .csv file and sent to an email address for further analysis. It seems like a fairly simple task and I am hoping someone has done something like this before and can help or point me in a direction where I can start. Thanks in advance.

      posted in Pythonista
      RoninSage
      RoninSage