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.
Interactive test
-
It seemed the best way to use the touch screen interface of the iPad. I am open to other suggestions.
-
@RoninSage Check this
Marvelous help -
@cvp, while I appreciate the shout-out for Gestures, it seems truly an overkill for this use case, as is Scene.
Quickest way to get this going would probably be
console.alert
, which lets you show a title (e.g. โQuestion #1โ), the question, and three options for answers.If you want more fancy graphics, a custom ui.View with a TextView and Buttons is quite straightforward as well. You can use the UI designer to create the layout.
Let us know what you need to get forward.
-
... and if you decide to go with the custom UI.View and want to get really fancy, with questions and answers flying in and out or other effects like that, then I would recommend Scripter to make managing the animations easier.
-
Here is an example implementation and I hope it helps
https://gist.github.com/4e520ac2104b902b7a2394d4e7855fa3 -
I tried it with scene
from scene import Scene, Node, LabelNode, run class quiz(Scene): def __init__(self): super().__init__() self.pages = [] def setup(self): self.page_now = -1 self.buttons = Node() self.add_child(self.buttons) temp = LabelNode("start quiz?") temp.position = self.size/2 self.buttons.add_child(temp) def touch_began(self, touch): for i in self.buttons.children: if touch.location in i.bbox: if self.page_now < len(self.pages)-1: self.next_page() print("userer picked:", i.text) else: print("end of quiz") def next_page(self): self.buttons.remove_from_parent() self.page_now += 1 question, values = self.pages[self.page_now] page = Node() num_of_nodes = len(values) + 1 h = self.size.h / num_of_nodes w = self.size.w x = self.size.w * 0.5 but = LabelNode(question, font=('Helvetica', 40)) values.append("") for i in range(len(values)): but.anchor_point = (0.5, 1) but.position = (x, self.size.y - (h*i)) but.y_scale = min(w / but.size.x, h/but.size.y) but.x_scale = min(w / but.size.x, h/but.size.y) page.add_child(but) but = LabelNode(values[i], font=('Helvetica', 40)) self.buttons = page self.add_child(page) def add_page(self, question, values): self.pages.insert(-2, (question, values)) if __name__ == "__main__": app = quiz() app.add_page("do you like this code", ["yes", "no"]) app.add_page("do you understand this code", ["yes", "no", "whats code lol"]) app.add_page("if you add lots of text it gets smallergggggggggggggggggggggggggggggggggggggggg", ["oh ok, cool"]) run(app)
-
@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])
-
@RoninSage, some suggestions:
- You do not need to compile the whole list of fonts every time - you can just set the font by the name you find in the font picker ('+' above the keyboard, on the right).
- You do not need to include the whole code for gestures, you can just
import
it. - Again, you do not really need gestures for the most part, just for the edge swipe to proceed. For tapping the answers I would simplify the code a lot by just using ui.Buttons, all with
action
set to the same handler function that distinguishes which button was tapped by the name of the center. - For saving the answers, do you have a distinct need for CSV, instead of something slighly more robust?
-
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
-
@RoninSage already shorter ๐
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 to create key buttons def create_btn(btn_label,btn_name,btn_x,btn_y,btn_width): btn_name = ui.Button(title=btn_label,name=btn_name) if btn_label == 'delete': btn_name.action = btndel_tap elif btn_label == 'enter': btn_name.action = btnenter_tap else: btn_name.action = btn_tap 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 btn_tap(sender): txt_fld.text=txt_fld.text + sender.title def btndel_tap(sender): txt_fld.text=txt_fld.text[:-1] 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 for subv in view.subviews: if type(subv) is ui.Button: view.remove_subview(subv) view.close() # Create key buttons create_btn('1', 'btn1',view.width*0.0,view.height*0.66,view.width*0.04) create_btn('2', 'btn2',view.width*0.05,view.height*0.66,view.width*0.04) create_btn('3', 'btn3',view.width*0.1,view.height*0.66,view.width*0.04) create_btn('4', 'btn4',view.width*0.15,view.height*0.66,view.width*0.04) create_btn('5', 'btn5',view.width*0.2,view.height*0.66,view.width*0.04) create_btn('6', 'btn6',view.width*0.25,view.height*0.66,view.width*0.04) create_btn('7', 'btn7',view.width*0.3,view.height*0.66,view.width*0.04) create_btn('8', 'btn8',view.width*0.35,view.height*0.66,view.width*0.04) create_btn('9', 'btn9',view.width*0.4,view.height*0.66,view.width*0.04) create_btn('0', 'btn0',view.width*0.45,view.height*0.66,view.width*0.04) create_btn('delete', 'btndel',view.width*0.505,view.height*0.66,view.width*0.09) create_btn('q', 'btnq',view.width*0.025,view.height*0.73,view.width*0.04) create_btn('w', 'btnw',view.width*0.075,view.height*0.73,view.width*0.04) create_btn('e', 'btne',view.width*0.125,view.height*0.73,view.width*0.04) create_btn('r', 'btnr',view.width*0.175,view.height*0.73,view.width*0.04) create_btn('t', 'btnt',view.width*0.225,view.height*0.73,view.width*0.04) create_btn('y', 'btny',view.width*0.275,view.height*0.73,view.width*0.04) create_btn('u', 'btnu',view.width*0.325,view.height*0.73,view.width*0.04) create_btn('i', 'btni',view.width*0.375,view.height*0.73,view.width*0.04) create_btn('o', 'btno',view.width*0.425,view.height*0.73,view.width*0.04) create_btn('p', 'btnp',view.width*0.475,view.height*0.73,view.width*0.04) create_btn('๐', 'btnsf',view.width*0.525,view.height*0.73,view.width*0.04) create_btn('a', 'btna',view.width*0.05,view.height*0.8,view.width*0.04) create_btn('s', 'btns',view.width*0.1,view.height*0.8,view.width*0.04) create_btn('d', 'btnd',view.width*0.15,view.height*0.8,view.width*0.04) create_btn('f', 'btnf',view.width*0.2,view.height*0.8,view.width*0.04) create_btn('g', 'btng',view.width*0.25,view.height*0.8,view.width*0.04) create_btn('h', 'btnh',view.width*0.3,view.height*0.8,view.width*0.04) create_btn('j', 'btnj',view.width*0.35,view.height*0.8,view.width*0.04) create_btn('k', 'btnk',view.width*0.4,view.height*0.8,view.width*0.04) create_btn('l', 'btnl',view.width*0.45,view.height*0.8,view.width*0.04) create_btn('๐', 'btnhf',view.width*0.5,view.height*0.8,view.width*0.04) create_btn('z', 'btnz',view.width*0.075,view.height*0.87,view.width*0.04) create_btn('x', 'btnx',view.width*0.125,view.height*0.87,view.width*0.04) create_btn('c', 'btnc',view.width*0.175,view.height*0.87,view.width*0.04) create_btn('v', 'btnv',view.width*0.225,view.height*0.87,view.width*0.04) create_btn('b', 'btnb',view.width*0.275,view.height*0.87,view.width*0.04) create_btn('n', 'btnn',view.width*0.325,view.height*0.87,view.width*0.04) create_btn('m', 'btnm',view.width*0.375,view.height*0.87,view.width*0.04) create_btn('enter', 'btnenter',view.width*0.425,view.height*0.87,view.width*0.09) # 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
-
@RoninSage still shorter
# Create key buttons def create_row(row_labels,row_x,row_y): x = row_x for btn_label in row_labels: create_btn(btn_label,'btn'+btn_label, view.width*x, view.height*row_y, view.width*0.04) x = x + 0.05 create_row('1234567890', 0.0,0.66) create_btn('delete', 'btndel',view.width*0.505,view.height*0.66,view.width*0.09) create_row('qwertyuiop๐', 0.025,0.73) create_row('asdfghjkl๐', 0.05,0.8) create_row('zxcvbnm', 0.075,0.87) create_btn('enter', 'btnenter',view.width*0.425,view.height*0.87,view.width*0.09)
-
@RoninSage Additional infos
- button name is not needed because we remove them by sub_view of view
-
@cvp perfect, that simplified all the repetions and I still understand what is going on, thanks heaps.