checking for integers inside of a ui textfield
I'm trying to check if a textfield in my ui has any numbers in it when I press on a button. When I use the same code on a string it works. When I use the code for textfield within a button's action it doesn't work. Please help? Here's what my code is like:
import ui import console def contains_digits(d): for char in d: if char.isdigit(): return True return False test='test3' print(contains_digits(test)) #this works - it prints TRUE! #below always prints failed even though it should print whatever is in the textfield?! def button_pushed(sender): if contains_digits(textfield1): print(textfield1) print('failed') v=ui.load_view() textfield1 = str(v['textfield1'].text) v.present('fullscreen')
To debug this problem, print textfield when entering button_pushed.
As a reminder, strings in pythons are their own object, not pointers.
>a='hello' >b=a >a='world' >print(a==b) False
By the way, in case you have never used pdb before, this can really be useful.
def button_pushed(sender): import pdb pdb.set_trace()
now, when you push the button, type
Thanks so much for your help here. It seems that it's a problem with the variable - textfield1
Doing what you said - textfield1 prints nothing to the console and v['textfield1'].text prints whatever was typed into the textfield
Do you happen to know anyway in which I can use a variable to print to the console using the button?
I think I understand the issue from how you've explained it - the variable textfield1 starts of as "" and so even when it changes it's always going to remain as "", in order for me to put it into a variable - I'd have to put it into a variable within the function, when it's already set as whatever the user has set it as.
I think I may have answered my own question there?
Yep. Just use v['textfield1'].text, or store a refernce to the actual textfield object, then you can print the .text attribute.
@wenchoheelio , below is another way to consider filtering your TextField. Ie using a TextField Delegate. This way you are getting a peek at the key before it makes it into the TextField(you can accept or reject it, by either returning True or False). Below I have just copied the standard Delegate from the Pythonista Documentation. I just modified the textfield_should_change callback.
I could have deleted all the other methods in the class as in this case I am not using them. They will just do their default behaviour if they are not there. I point that out because the code looks longer and more complicated that it needs to to handle your case. I left them in so it was easy to see the other events you can take control of. Basically meaning you can have a lot of control over the data entry into the TextField.
Btw, I am looping over the replacement as it maybe a string that is being pasted into the textfield. You can try it by copying say '123456' and pasting it into your field. It will appear. But then try pasting '123456R' into the field, that will not work.
Hope it helps.
import ui class MyTextFieldDelegate (object): def textfield_should_begin_editing(self, textfield): return True def textfield_did_begin_editing(self, textfield): pass def textfield_did_end_editing(self, textfield): pass def textfield_should_return(self, textfield): textfield.end_editing() return True def textfield_should_change(self, textfield, range, replacement): for c in replacement: if not c.isdigit(): return False return True def textfield_did_change(self, textfield): pass class MyClass(ui.View): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.make_view() def make_view(self): tf = ui.TextField(frame=(0, 0, self.width, 32)) tf.delegate = MyTextFieldDelegate() self.add_subview(tf) if __name__ == '__main__': f = (0, 0, 300, 400) v = MyClass(frame=f) v.present(style='sheet', animated=False)
@Phuket2 Thanks, I really appreciate the time you've taken to write this.
I don't fully understand the super() part here. Not sure I really need to understand or use it early on? Also, I understand arguments/parameters - but what's *args, **kwargs ?Does that mean something? Arguments and KW arguments?!
What is this code for? It doesn't look like the function requires a parameter? (obviously it does.. I just don't understand it)
MyClassis a subclass of
ui.Viewalready has its own
__init__method, and now we also define an
__init__method in our subclass. By default, our subclass
__init__would completely replace the
ui.View. This would not be good, because then the code in
ui.View.__init__would never run for our
MyClassviews, and they would not be set up properly. To avoid this, we call
super().__init__(*args, **kwargs), which is (in this case) a shortcut for
ui.View.__init__(self, *args, **kwargs). That is, we let
ui.Viewinitialize our custom view before we do our own initialization.
**kwargssyntax is used here to pass all arguments from our own
__init__to the superclass
__init__. In a function/method definition,
*argsstands for "accept any number of positional (unnamed) arguments and put them into
argsas a tuple", and
**kwargsstands for "accept any number of keyword (named) arguments and put them into
kwargsas a dictionary". In a function/method call, they do basically the opposite, and pass the contents of the given tuple/dictionary as arguments.