Forum Archive

Segmentation fault in real numeric pad on iPad

cvp

For @estephan500 and @runjaj I begin to (try to) create a real numeric pad on iPad.
The code is not yet finished nor nice but when I test it, I get a segmentation fault when I type the backspace key for the 2nd time...
Help of a guru is needed 😢

import ui
from objc_util import *

# To store TextField associated with key-button, we need to use a python class
# for the button, not an ui.Button it-self
# idea found here https://forum.omz-software.com/topic/1913/attaching-a-class-to-a-ui-element-such-as-uibutton-i-am-desperate
class CustomAction(object):
        def __init__(self, TextField):
            self.action = self.real_action
            self.TextField = TextField

        def __call__(self, sender):
            return self.action(sender)

        def real_action(self, sender):

            tfb = self.TextField
            if sender.name == 'x':
                if tfb.text != '':
                    tfb.text = tfb.text[:-1]
            elif sender.name == 'y':
                tfb.end_editing()
            else:
                tfb.text = tfb.text + sender.title

def SetTextFieldAsNumeric(tf):
    tfo = ObjCInstance(tf).textField() # UITextField is subview of ui.TextField
    #print(dir(tfo))

    keys = '123x|456|789y| 0'
    #keys = '1234567890x y'
    rows = keys.split('|')
    row_length = 0
    for row in rows:
        if len(row) > row_length:
            row_length = len(row)

    v = ui.View()
    db = 50
    dd = 10
    x0 = (ui.get_screen_size()[0]-row_length*db-(row_length-1)*dd)/2
    x = x0
    y = 0

    for row in rows:
        for c in row:
            if c != ' ':
                b = ui.Button()
                b.name = c
                b.background_color = 'white'
                b.tint_color = 'black'
                b.corner_radius = 10 
                if c == 'x':
                    b.image = ui.Image.named('typb:Delete')
                elif c == 'y':
                    b.title = ''
                    b.image = ui.Image.named('iob:ios7_checkmark_outline_32')
                else:
                    b.title = c
                b.font = ('<system>',32)
                b.frame = (x,y,db,db)
                b.action = CustomAction(tf) # to store TextField in button
                v.add_subview(b)
            x = x + db + dd
        y = y + db + dd
        x = x0

    v.width = ui.get_screen_size()[0]
    v.height = y

    # view of keyboard
    tfo.setInputView_(ObjCInstance(v))

tf = ui.TextField()

SetTextFieldAsNumeric(tf)
tf.text = ''
tf.present('sheet')
tf.begin_editing()
tf.wait_modal()
cvp

reading here solves the problem, add:

    retain_global(v)

Before

    tfo.setInputView_(ObjCInstance(v))
JonB

really great idea!

by the way, in recent pythonista versions, you can add attributes to buttons directly. therefore, you can say
b.Textfield =Textfield,
and your button action can therefore access sender.Textfield.
That CustomAction was for previous versions where you could not add custom attributes to buttons.

cvp

@JonB Thanks a lot, will make code easier