Hey guys, I'm new to pythonista and I need your help. I want to create a kind of calculator. I have tried it so many times, but my result has never been accepted.
In the blue circle you should specify the number.
In the yellow circle is the price of the product.
In the red circle is the "Ok" button, which calculates the number of specified products.
In the green circle then the result, so the price stand.
It would be nice if you could help me, because as a beginner I really despair of it. it would be nice if you could explain your steps.
Thank you!
[link text](Sieh dir den Tweet von @Someuse79137145 an: https://twitter.com/Someuse79137145/status/1101238789593284609?s=09
Forum Archive
can u help me Out?
@some-user Quick and dirty
import ui
items = {}
items['tomate'] = 2
items['salami'] = 1.5
items['käse'] = 1.5
items['butter'] = 1.5
items['frischkäse'] = 1.5
mv = ui.View()
mv.frame = (0,0,500,600)
mv.name = 'test'
d = 10
h = 32
y = d
for item in sorted(items.keys()):
p = items[item]
l = ui.Label()
l.frame = (d,y,200,h)
l.text = item
mv.add_subview(l)
n = ui.TextField(name=item)
n.frame = (l.x+l.width+d,y,50,h)
mv.add_subview(n)
lp = ui.Label()
lp.frame = (n.x+n.width+d,y,50,h)
lp.alignment = ui.ALIGN_RIGHT
lp.text = '{0:.2f}'.format(p) + ' €'
mv.add_subview(lp)
y = y + h + d
def b_action(sender):
t = 0
for item in items.keys():
try:
t = t + float(items[item]) * float(mv[item].text)
except:
pass
sender.superview['total'].text = '{0:.2f}'.format(t) + ' €'
b = ui.Button()
b.frame = (lp.x+lp.width+d,y,50,h)
b.border_width = 1
b.corner_radius = 5
b.title = 'ok'
b.action = b_action
mv.add_subview(b)
ltot = ui.Label(name='total')
ltot.frame = (d,y,100,h)
ltot.border_width = 1
ltot.corner_radius = 5
ltot.alignment = ui.ALIGN_RIGHT
mv.add_subview(ltot)
y = y + h + d
mv.height = y
mv.present('sheet')

@cvp Hey, thank you! You helped me a lot and I notice that I would not have made it without help. Maybe it is very easy for you :) but I do not really look like that yet. could you possibly explain the steps to me? But really thank you for taking the time! :)
n.keyboard_type = ui.KEYBOARD_NUMBER_PAD will keep the input numeric on iPhones but not on iPads.
The OK button is off the screen on an iPhone 7 unless you switch to landscape mode.
@some-user see comments in code
import ui
# init dictionnary with items names and unit proces
items = {}
items['tomate'] = 2
items['salami'] = 1.5
items['käse'] = 1.5
items['butter'] = 1.5
items['frischkäse'] = 1.5
# create main View
mv = ui.View()
mv.frame = (0,0,500,600)
mv.name = 'test'
# init some parametrized dimensions, you could change to see effect
d = 10 # horizontal and vertical distance between contiguous fields
h = 32 # height of fields
y = d # initial y
for item in sorted(items.keys()): # loop on items, sorted by names
p = items[item] # get item price from dictionnary
# create Label for item name
l = ui.Label()
l.frame = (d,y,200,h) # its area in main view x,y,dx,dy
l.text = item # init it with item name
mv.add_subview(l) # set the label as field of main view
# create TextField for entry of number of items
n = ui.TextField(name=item) # set its name as the item name
n.keyboard_type = ui.KEYBOARD_NUMBER_PAD # use numeric keyboard
n.frame = (l.x+l.width+d,y,50,h) # its area in main view
mv.add_subview(n)
# create Label for unit price
lp = ui.Label()
lp.frame = (n.x+n.width+d,y,50,h) # its area
lp.alignment = ui.ALIGN_RIGHT # align the text at right
lp.text = '{0:.2f}'.format(p) + ' €' # format the unit price as '1.23 €'
mv.add_subview(lp)
# compute vertical position y for next row
y = y + h + d
# define the code to execute when ok is tapped
def b_action(sender):
t = 0 # init total
for item in items.keys(): # loop on items
try: # protect if number not filled or not numeric
n = float(mv[item].text) # get entered number in textfield named item
t = t + float(items[item]) * n # cumulate price x n
except:
pass
# fill result field with total formatted as '123.45 €'
sender.superview['total'].text = '{0:.2f}'.format(t) + ' €'
# create button for ok
b = ui.Button()
b.frame = (lp.x+lp.width+d,y,50,h) # its area
b.border_width = 1 # display a border to button
b.corner_radius = 5 # with rounded corners
b.title = 'ok'
b.action = b_action # which code to execute of tapped
mv.add_subview(b)
# create Label to display computed total
ltot = ui.Label(name='total') # give a name to access it in b_action code
ltot.frame = (d,y,100,h)
ltot.border_width = 1
ltot.corner_radius = 5
ltot.alignment = ui.ALIGN_RIGHT
mv.add_subview(ltot)
y = y + h + d # compute y at bottom of last total field
mv.height = y # setof displayed main view
mv.present('sheet') # present the main view and wait
@cvp it does not work for me? which tools did you use?
@cvp it does not work for me? which tools did you use?
I have a label for the name of the products and the price. At the input field of the number and at the result a textfield.
@some-user Sorry if I didn't correctly understand your post. Do you want also to enter the name of the items and their unit price?
@some-user Anyway, the result is a label even if it looks like a textfield due to its border
@cvp The specified products are entered with a number. And then come out together bottom left. for example
Tomato 4 (2 €)
Cheese 4 (1.50 €)
Salami 0 (1.50 €)
butter 0 (1.20 €)
Cream cheese 3 (1.50 €)
Is there product in a label? Or which tool would be used in the case?
After the product comes the number you should enter. Is that then a text field in the case? You have to enter a number. And behind is the price. Which tool do you use for this? Then press the "Ok" button, which is on the bottom right. The ok button calculates the whole thing and the result then appears on the lower left, in a field. In my example, the result would be, so the total price would be 18.50 €. That number would pop up, anyway. So that was just one example, the whole in the sketch I sent as a Twitter link. Thanks for your helpfulness :)
@cvp The specified products are entered with a number. And then come out together bottom left. for example
Tomate 4 (2 €)
Käse 4 (1.50 €)
Salami 0 (1.50 €)
Butter 0 (1.20 €)
Frischkäse 3 (1.50 €)
Is there product in a label? Or which tool would be used in the case?
After the product comes the number you should enter. Is that then a text field in the case? You have to enter a number. And behind is the price. Which tool do you use for this? Then press the "Ok" button, which is on the bottom right. The ok button calculates the whole thing and the result then appears on the lower left, in a field. In my example, the result would be, so the total price would be 18.50 €. That number would pop up, anyway. So that was just one example, the whole in the sketch I sent as a Twitter link. Thanks for your helpfulness :) I'm sorry, but I'm not checking it yet.
@some-user Sorry, but I leave today and not sure when I could answer...
@some-user Still one question: did you try my little script?
And you ask "which tool" but do you use the Pythonista app on iPhone/iPad or do you have an Android device like in your twitter image?
Here is a Pythonista forum, thus my question is obviously stupid.
@cvp Of course, I tried her script, but it did not work. So I thought I've made my ui wrong. That's why the question with the tools. I work with Pythonista on my iPad, but this is what I'm doing right now on my phone. I only work with my iPad and have no social media on it. Take your time. I think it's very friendly and not a matter of course that you help me and I'm really grateful.
@cvp Of course, I tried your script, but it did not work. So I thought I've made my ui wrong. That's why the question with the tools. I work with Pythonista on my iPad, but this is what I'm doing right now on my phone. I only work with my iPad and have no social media on it. Take your time. I think it's very friendly and not a matter of course that you help me and I'm really grateful.
You might get better help if you post your code and UI, and explain what your problem is.
To post a UI, you can tap the Edit button, in the library menu, select the pyui file and py file, then tap the share button, and then share to gist.
@some-user As my little dirty script works on my iPad, could you explain what doesn't work for you. Problem of screen dimensions? Error message?
@cvp So there is no error message with me. It turns up without any message. I enter the numbers and press the Ok button. But nothing happened. So I assumed that I have mis-designed my UI. Could you show me how you designed yours?
@some-user I can't show more than the script, all is included in it, without any external design, that's why I don't understand your question, I'm sincerely sorry.
Do you use my script without changing it?
If you run it on your iPad, do you also have troubles?
@some-user Perhaps I did not understand your post.
If you have your own script and your own UI design, and your script does not work as expected, in this case, as adviced by @JonB , post here your script and your .pyui file.
For this last one, you can share it as gist or rename the file as .txt, edit it, select all, copy and paste here in a post.
I'll not be able to help you before this evening...
@cvp sorry for the poor quality, but i had to go fast. So that's my script.pyui. It has a size of 600 x 600. My background is a custom view. I've always used labels in the red circles. In the blue circle I have used text fields so that there can be entered the number of products sold. In the yellow circle is the button that you click after entering the numbers. He calculates it and the result appears in the green circle, which is also a label.
Because it's wrong with me, I thought, I made it wrong. For example, to replace a text field with a label. That's why I asked you. I just copied out the code and used it. If I press Play then this picture appears exactly what you see in my Twitter link. I can enter numbers in the text field, but if I press the button nothing happens.
https://twitter.com/Someuse79137145/status/1102197985314779136?s=09
Turn your phone in landscape mode and then run the original app. The button is off the screen on older phones when they are in portrait mode.
@cvp I can not share this somehow. If I want to save it as a gist error code. I have it now as a file.
you need to either post the code (use triple backspace) in the forum, or use share to gist (you can try from the share menu when editing the .py code)
how else do you expect us to diagnose your code? your problem is on line 17, take a closer look at that line...
In general, I will say this:
When you boil down your problem, you have to do three or four things:
1) get a function to call when you wither update a textfield(maybe), or press OK.
2) Get the values of each quantity textfield, and convert to a double
3) Figure out which price goes with each quantity, then multiply qty*price, and add up the prices
4) update the result textfield
Why not take it step by step:
1) can you get a function to call when you press OK? Even just
def ok_action(sender):
print('hello world')
If you are using the pyui designer, note that you would fill out the button's action field with, in this case, ok_sender. in your script, you need to mKe sure that function def occurs prior to calling load_pyui.
2) sender gives you access to the button- but you need the textfield values... how can you get to the textfields, from the button?
There are two basic ways:
a) you can use sender.superview to get to your main view, then use subviews to walk through the otherviews, or else use the textview names. i.e sender.superview['qty1'], or textviews = [t for t in sender.superview.subviews if isinstance(t,ui.Textfield) and t.name.startswith('qty')]
where here i have assumed that instead of the default textfield1, etc names, you name your qty textfields as qty1, qty2, etc.
b) alternatively, you can set up a global variable to a list of textfields after you use load_view, then you dont need to use sender at all, just reference the list directly. this is more applicable for more complex ui's.
Before moving on, get your action to print out the value of each textfield to the console.
3) This is the tricky part-- how to figure out the price of each textfield... there are a few ways. the easiest is to add a custom attribute to each textfield in the pyui. then you are simply doing double(t.text)*t.price to get the price for each item. custom attributes are at the bottom of the ui designer where you set textfield info, and you'd enter something like {'price':1.75} in that field (you enter as a dict, which then gets set as attributes).
If you have the textfields as a list, then you are doing something like
sum([double(t.text)*t.price for t in textfields])
Other ways you could handle this:
a) if you have a textfield names qty1, name your label price1. then you would lookup the label title.
4) the last step should be easy if you have understood the steps above. now you are simply setting your result textfield.text. if you understood step 2, you understand how to find the result textfield from sender or from your main view. step 3 gives you the result. then you simple set the .text field of the textfield.
now, take it one step at a time. if you get an error you dont understand, tap Print Traceback, then copy the entire error to paste into your next message.
you really do need to share your code, or we cant help, except in general. try to post your code (from editor directly) - if sharing to gist is giving you an error, post a screenshot of the error!
@JonB Hey, thanks for your help. To clarify, I came here because I did not know what to do. I am quite a beginner. @ccc wrote me a script that you can see above as the first answer.
@JonB Hey, thanks for your help. To clarify, I came here because I did not know what to do. I am quite a beginner. @cvp wrote me a script that you can see above as the first answer.
In ~28~ lines just for the fun of it...
Now 34 lines with Ausgaben (expenses) added...
import ui
foods = {'Tomate-Mozarella Brötchen': 2,
'Salami Brötchen': 1.5,
'Käse Brötchen': 1.5,
'Butter Laugenstange': 1.2,
'Frischkäse Laugenstange': 1.5}
def button_action(sender):
total = sum(float(mv[food_name].text or 0) * unit_price
for food_name, unit_price in foods.items())
total -= float(mv['expenses'].text or 0)
mv['total'].text = f'{total:.2f} €'
mv = ui.View(frame=(0, 0, 360, 360), name=__file__.split('/')[-1])
d = 10 # horizontal and vertical distance between contiguous fields
h = 32 # height of fields
y = d # initial y
for i, (food_name, unit_price) in enumerate(foods.items()): # loop on foods
y = d + i * (h + d)
mv.add_subview(ui.Label(frame=(d, y, 215, h), text=food_name))
mv.add_subview(ui.TextField(frame=(d * 2 + 215, y, 50, h), name=food_name,
keyboard_type=ui.KEYBOARD_NUMBER_PAD)) # works on iPhones, not iPads
mv.add_subview(ui.Label(frame=(d * 3 + 265, y, 50, h),
text=f'{unit_price:.2f} €'))
y += h + d
mv.add_subview(ui.Label(frame=(d, y, 215, h), text='Ausgaben'))
mv.add_subview(ui.TextField(frame=(d * 2 + 215, y, 50, h), name='expenses',
keyboard_type=ui.KEYBOARD_DECIMAL_PAD)) # works on iPhones, not iPads
mv.add_subview(ui.Label(frame=(d * 3 + 265, y, 50, h), text='€'))
y += h + d
mv.add_subview(ui.Button(frame=(d * 3 + 265, y, 50, h), action=button_action,
border_width=1, corner_radius=5, title=' OK '))
mv.add_subview(ui.Label(frame=(d, y, 100, h), name='total', border_width=1,
corner_radius=5, alignment=ui.ALIGN_RIGHT))
mv.height = y + h + d
mv.present('sheet') # present the main view and wait
If you are designing with the pyui, read through the UI docs. It has some good basics.
Then, head over to https://github.com/humberry/ui-tutorial
@ccc OK wow, you are my hero, thank you very much. It works fine. There is only one more thing left. And indeed, there is still a field with the expenditure of food. That is, enter a number in a field and it will be deducted from the result. I know you have done so much for me and that would be my last one please. And I must confess that I would never have done that without your help. Thank you!!!!
@some-user You are underestimating yourself, if you take the time to start with very simple examples, you will be able to do what you want. @ccc's example is probably a little advanced -- a good olace to aspire to, but i think you ought to start with ui's containing one button and one textbox, and understand how to read or fill the textbox.
@cvp Okay, I have to apologize profoundly to you. Do you know what the problem was? I have not taken a blank script but a script with a UI. I designed my ui and that's why the code did not work. I'm sorry I wasted your time on such stupid problems. Could you please do one more thing for me? And add one more field, in which you can also enter a number. This number is then subtracted from the calculated result. That's the cost of the food needed for the products. https://twitter.com/Someuse79137145/status/1102328019795042304?s=09
@cvp anderen make Sure u got the place :). Thank you https://twitter.com/Someuse79137145/status/1102328791274278913?s=09
I added Ausgaben (expenses) to my solution above.
@some-user Sorry to answer so/too late. No problem at all, believe me.
I've made myself so much errors that I'm happy to not be the only one 😂
Welcome in this marvelous app and its marvelous forum
Edit: you asked me to add a field but as @ccc already did it, I guess I don't have to do it.
@cvp It would be nice if you could do it too. It's very nice of ccc but I can understand your code better. But if they do not feel like they do not have to do it. I would be very grateful.
@some-user I write it easily understood but the code of @ccc is more professional and also supports the iPhone. I'll include his additional field this afternoon.
@some-user try this, taken in account dimensions in @ccc code
import ui
# init dictionnary with items names and unit proces
items = {}
items['tomate'] = 2
items['salami'] = 1.5
items['käse'] = 1.5
items['butter'] = 1.5
items['frischkäse'] = 1.5
# create main View
mv = ui.View()
mv.frame = (0,0,360,360)
mv.name = 'test'
# init some parametrized dimensions, you could change to see effect
d = 10 # horizontal and vertical distance between contiguous fields
h = 32 # height of fields
y = d # initial y
for item in sorted(items.keys()): # loop on items, sorted by names
p = items[item] # get item price from dictionnary
# create Label for item name
l = ui.Label()
l.frame = (d,y,215,h) # its area in main view x,y,dx,dy
l.text = item # init it with item name
mv.add_subview(l) # set the label as field of main view
# create TextField for entry of number of items
n = ui.TextField(name=item) # set its name as the item name
n.keyboard_type = ui.KEYBOARD_NUMBER_PAD # use numeric keyboard
n.frame = (d*2+215,y,50,h) # its area in main view
mv.add_subview(n)
# create Label for unit price
lp = ui.Label()
lp.frame = (d*3+265,y,50,h) # its area
lp.alignment = ui.ALIGN_RIGHT # align the text at right
lp.text = '{0:.2f}'.format(p) + ' €' # format the unit price as '1.23 €'
mv.add_subview(lp)
# compute vertical position y for next row
y = y + h + d
# create Label for expenses title
l = ui.Label()
l.frame = (d,y,215,h) # its area in main view x,y,dx,dy
l.text = 'Ausgaben'
mv.add_subview(l) # set the label as field of main view
# create TextField for entry of xpenses
ex = ui.TextField(name='expenses')
ex.keyboard_type = ui.KEYBOARD_DECIMAL_PAD # works on iPhones, not iPads
ex.frame = (d*2+215,y,50,h) # its area in main view
mv.add_subview(ex)
# create Label for €
l = ui.Label()
l.frame = (d*3+265,y,50,h) # its area in main view x,y,dx,dy
l.text = '€'
mv.add_subview(l) # set the label as field of main view
y = y + h + d
# define the code to execute when ok is tapped
def b_action(sender):
t = 0 # init total
for item in items.keys(): # loop on items
try: # protect if number not filled or not numeric
n = float(mv[item].text) # get entered number in textfield named item
t = t + float(items[item]) * n # cumulate price x n
except:
pass
try:
t = t - float(mv['expenses'].text)
except:
pass
# fill result field with total formatted as '123.45 €'
sender.superview['total'].text = '{0:.2f}'.format(t) + ' €'
# create button for ok
b = ui.Button()
b.frame = (d*3+265,y,50,h) # its area
b.border_width = 1 # display a border to button
b.corner_radius = 5 # with rounded corners
b.title = 'ok'
b.action = b_action # which code to execute of tapped
mv.add_subview(b)
# create Label to display computed total
ltot = ui.Label(name='total') # give a name to access it in b_action code
ltot.frame = (d,y,100,h)
ltot.border_width = 1
ltot.corner_radius = 5
ltot.alignment = ui.ALIGN_RIGHT
mv.add_subview(ltot)
y = y + h + d # compute y at bottom of last total field
mv.height = y # setof displayed main view
mv.present('sheet') # present the main view and wait
@cvp Thank you, but there is still a problem. If "Ausgaben" is a number with a comma (for example, 3.33), it will not be considered. I tried to get it myself but it just does not work for me. If you can do that, you must explain that to me.
@some-user You, like me, will need to wait a little bit because my iPad is busy with my granddaughter who is playing Fortnite on it and I'll never dare to interrupt her 😂
@some-user Just an idea: I can't test without iPad (see above 😥), but did you try 3,33 and 3.33 because, in function of your keyboard language, one is taken as a string, thus refused, the other one as a number, thus accepted
@cvp Omg, I'm so stupid. Thank you for your help. I would never have done it without you. Maybe I will contact you again if I do not get something in the script. Thank you.
@some-user In this forum, there is no stupid because you use Pythonista 😂 Be sure, we all do some errors...
@cvp okay one more question. How do I add this to my homescreen now? If I want to do that, I'll be redirected to Safari. Then it says I should add this to my homescreen. But that looks like that
https://twitter.com/Someuse79137145/status/1102583731959808000?s=09
@some-user I suppose you use the standard version of app, not the beta. I don't have any more this version thus I can't test the shortcut creation of this version but what you get is really not normal. It seems like the Safari page is an url, not a data...
what happens when you click on your icon?
@cvp it opens the app and runs the Script
@some-user ok, that's normal but not the icon it-self
@JonB
Spotted your pointer to the GitHub humberry UI Tutorial, excitedly skipped over to GitHub
As I really do want to “get” using pyui’s....
Aargh! New Brick Walls!
It may sound simple but how do I get a GitHub resident PYUI file to my iPad.
You cannot imagine what I have tried so far, including forking the Tutorial!
Yours incompetently
Adrius42
There are a few ways to get a github repo onto your iPad.
1) install https://github.com/ywangd/stash, which if you read the readme comes with its own simple install script
Then you have a git command, which can clone a repo. You need to run stash using py2.7 for this to work.
2) on a recent device, you can install the Working Copy app, which let's you clone repos, and has integration with pythonista.
3) every GitHub repo has a zip download address, you can use wget in stash, or requests or urllib to download, then unzip it.
4) pythonista tools has various tools, of various pedigree:
https://github.com/Pythonista-Tools/Pythonista-Tools/blob/master/GitHub%20Tools.md
Some may not work at all in current pythonista versions...
@adrius42 there is a more manual workaround to copying pyui files from GitHub into Pythonista:
1. Go to the .pyui file’s webpage on GitHub
2. Click the Raw button near the upper right of that page.
3. Select all the text and tap Copy
4. Go back to Pythonista and create a new script
5. Paste the text into that script
6. Rename the script to change its file extension from .py to .pyui
@some-user If you want to be able to "go to next input field" by a key, see here
Example: next number of items