Updating Total button with with Button click from calculations - python

I am making a point of sale systems and one of the important things I'm trying to make is a total button or just a total. So when the total button is pressed, or every time an item is added, the total will be recalculated and outputted.
I started off with just declaring the variables:
item1_qty = 0
item2_qty = 0
item3_qty = 0
item4_qty = 0
item5_qty = 0
item6_qty= 0
item7_qty = 0
item8_qty = 0
item1_price = 0
item2_price = 0
item3_price = 0
item4_price = 0
item5_price = 0
item6_price = 0
item7_price = 0
item8_price = 0
itemTotal=0
and I'm using this code for the actual item buttons (I have 4 currently just so I don't get confused but I've included the first 2)
#Item1 Button + Function
def item1_Button():
global item1_qty
item1_text = ("Chips")
item1_price = "2.00"
item1_qty += 1
item1_text = (item1_text + " "+item1_price +" "+ str(item1_qty)) #concatonates text & variable
item1.config(text=item1_text) #updates label text - doesn't add multiple
item1.place(x=0, y=0) #places label within the frame
item1_Button = Button(itemFrame, text="Chips", width=10, height=10, command=item1_Button)
#creates button + links to function
item1_Button.grid(row=1, column=1) #positions button
item1 = Label(receiptFrame)#creates label for button
#Item2 Button + Function
def item2_Button():
global item2_qty
item2_text = "Fish & Chips"
item2_price = "5.00"
item2_qty += 1
item2_text = (item2_text + " "+item2_price +" "+ str(item2_qty)) #concatonates text & variable
item2.config(text=item2_text) #updates label text - doesn't add multiple
item2.place(x=0, y=50)
item2_Button = Button(itemFrame, text="Fish & Chips", width=10, height=10, command=item2_Button)
item2_Button.grid(row=1, column=2)
item2 = Label(receiptFrame)
I'm not entirely sure what I'm doing in terms of the actual total button, so I have kind of just started off with this:
def updateTotal():
global item1_price, item2_price, item3_price, item4_price
global item1_qty, item2_qty, item3_qty, item4_qty
itemPrice = item1_price + item2_price + item3_price + item4_price
itemQuantity = item1_qty + item2_qty + item3_qty + item4_qty
itemTotal = (itemPrice * itemQuantity)
totalPrice.config(text=str(itemTotal))
totalPrice = Label(totalFrame, font=("arial", 25), text="0"+str(itemTotal))
totalPrice.place(x=10, y=10)
totalButton = Button(totalFrame, text="Total", command=updateTotal, width=15, height=5)
totalButton.place(x=450, y=0)
Is there something I need to do different in terms of how I use the variables?
I would prefer if the total was just text that updated every time an Item button was clicked instead of a Total button but I would appreciate some guidance as nothing is happening at the moment and I'm not entirely sure what I need to do as I'm fairly new with tkinter.

You didnt provide a minimal reproducible example and this post is 2 months old so im not gonna really explain the code and it is mostly self explanatory.
used f-strings, they are like this:
intensifier = input("Enter an intensifier: ")
adjective = input("Enter an adjective: ")
sentence = f"This is {intensifier} {adjective}"
print(sentence)
The curly-brackets let you enter none string values and are automatically turned into a string. (Useable in most scenarios and no concatenation)
Changed items into lists, lists can be used like this:
list1 = ["value1",2,[value3]]
print(list1[0]) #Would print, "value1"
print(list1[1:2])#Would print, [2,[value3]]
Listbox is a box of lists, you can add stuff into it using
listbox.insert(<place to add to>, <object to add>)
Full Code:
from tkinter import *
root = Tk()
root.title("Receipt System")
items_qty = [0,0,0,0]
items_price = [2,5,0,0]
items_text = ["Chips","Fish&chips","",""]
global itemTotal #Global variable
items_total = [0,0,0,0]
currency = "£" #Sets currency
#Functions
def addItem(x):
items_qty[x] += 1 #Adds 1
totalPrice = items_qty[x] * items_price[x] #quantity * price
text = f"{items_qty[x]}x {items_text[x]} {currency}{totalPrice}"
for i in range(0, receipt.size()):
if items_text[x] in receipt.get(i):
receipt.delete(i)
receipt.insert(END, text)
updateTotal(x)
def updateTotal(x):
global items_total
items_total[x] = items_qty[x] * items_price[x] #quantity * price
total = 0
for i in range(0, len(items_total)):
total += items_total[i]
totalPrice.config(text=f"Total: {currency}{str(total)}")
#UI
itemFrame = Frame(root)
itemFrame.pack(pady = 10)
receiptFrame = Frame(root)
receiptFrame.pack(pady = 10)
item1Btn = Button(itemFrame, text=f"Chips - {currency}{items_price[0]}", command=lambda: addItem(0)).pack(side = LEFT, padx = 10)
item2Btn = Button(itemFrame, text=f"Fish & Chips - {currency}{items_price[1]}", command=lambda: addItem(1)).pack(side = LEFT, padx =10)
receipt = Listbox(receiptFrame, selectmode = SINGLE, width = 30) #Receipt list
receipt.pack()
totalPrice = Label(receiptFrame, text = f"Total: {currency}0")
totalPrice.pack(pady = 10)
root.mainloop()

Related

Why exec function in python adds '.!' at the beginning of the text?

I am currently working on a hangman game using tkinter in python.
When I click a button of the letter and it is in the word that we are guessing it should show the letter. But when I click the button this problem is popping up:
This example is only with one button. People say that this problem is because of the mainloop(), but i have no idea how to fix it.
from tkinter import *
from tkinter import messagebox
from generate_word import word
#DEFAULT VALUES
score = 0
count = 0
win_count = 2
WINDOW_BG = '#e5404e'
WINDOW_SIZE = '1200x870+300+80'
FONT = ('Arial', 40)
from tkinter import *
from tkinter import messagebox
from generate_word import word
#DEFAULT VALUES
score = 0
count = 0
win_count = 2
WINDOW_BG = '#e5404e'
WINDOW_SIZE = '1200x870+300+80'
FONT = ('Arial', 40)
#this is an example with only one button
buttons = [['b1','a',80,740]]
#Creating window and configurating it
window = Tk()
window.geometry(WINDOW_SIZE)
window.title('Hangman')
window.config(bg = WINDOW_BG)
#generates all of the labels for the word
def gen_labels_word():
label = Label(window, text = " ", bg = WINDOW_BG, font = FONT)
label.pack( padx = 40,pady = (500,100),side = LEFT)
label1 = Label(window, text = word[0], bg = WINDOW_BG, font = FONT)
label1.pack( padx = 41,pady = (500,100),side = LEFT)
x = 21
for var in range(1,len(word)):
exec('label{}=Label(window,text="_",bg=WINDOW_BG,font=FONT)'.format(var))
exec('label{}.pack(padx = {}, pady = (500,100), side=LEFT)'.format(var,x))
x += 1
exec('label{} = Label(window, text = "{}", bg = WINDOW_BG, font = FONT)'.format(len(word),word[-1]))
exec('label{}.pack( padx = {},pady = (500,100),side = LEFT)'.format(len(word), x+1))
# ---------------------------------------------------------------------------------------------------------------------------------------------------
gen_labels_word()
#----------------------------------------------------------------------------------------------------------------------------------------------------
#letters icons(images)
#hangman (images)
hangman = ['h0','h1','h2','h3','h4','h5','h6']
for var in hangman:
exec(f'{var}=PhotoImage(file="{var}.png")')
han = [['label0','h0'],['label1','h1'],['label2','h2'],['label3','h3'],['label4','h4'],['label5','h5'],['label6','h6']]
for p1 in han:
exec('{}=Label(window, bg = WINDOW_BG ,image={})'.format(p1[0],p1[1]))
exec('label0.place(x = 620,y = 0)')
for var in letters:
exec(f'{var}=PhotoImage(file="{var}.png")')
for var in buttons:
exec(f'{var[0]}=Button(window,bd=0,command=lambda: game_brain("{var[0]}","{var[1]}"),bg = WINDOW_BG,font=FONT,image={var[1]})')
exec('{}.place(x={},y={})'.format(var[0],var[2],var[3]))
def game_brain(button, letter):
global count,win_count,score
exec('{}.destroy()'.format(button))
if letter in word:
for i in range(1,len(word)):
if word[i] == letter:
win_count += 1
exec(f'label{i}.config(text="{letter}")')
if win_count == len(word):
score += 1
messagebox.showinfo('GOOD JOB, YOU WON!\n GOODBYE!')
window.destroy()
else:
count += 1
exec('label{}.destroy()'.format(count-1))
exec('label{}.place(x={},y={})'.format(count,620,0))
if count == 6:
messagebox.showinfo('GAME OVER','YOU LOST!\nGOODBYE!')
window.destroy()
def EXIT():
answer = messagebox.askyesno('ALERT','Do you want to exit the game?')
if answer == True:
window.destroy()
e1 = PhotoImage(file = 'exit.png')
ex = Button(window,bd = 0,command = EXIT,bg = WINDOW_BG,font = FONT,image = e1)
ex.place(x=1050,y=20)
#-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
window.mainloop()
Why exec function in python adds '.!' at the beginning of the text?
The exec function isn't doing that. Tkinter by default names all of its widgets with a leading exclamation point. When you print out a widget, it has to be converted to a string. For tkinter widgets, the result of str(some_widget) is the widget's name.
You can see this quite easily without exec:
import tkinter as tk
root = tk.Tk()
label = tk.Label(root)
print(label)
The above will print something like .!label. If you create a second label it will be .!label2, a third will be .!label3 and so on.
On an unrelated note, you shouldn't be using exec to create widgets. It makes the code very hard to understand and debug. If you want to create widgets in a loop, add them to a dictionary or list instead of dynamically creating variables with exec.
For example:
labels = {}
for var in range(1,len(word)):
label = Label(window,text="_",bg=WINDOW_BG,font=FONT)
label.pack(padx=500, pady=100)
labels[var] = label
With that, you can later reference the widgets as labels[1], labels[2], etc.
You should do the same thing with the images, or anything else that you create in a loop and want to keep track of.

Text Game to Tkinter GUI [duplicate]

This question already has answers here:
Why is my Button's command executed immediately when I create the Button, and not when I click it? [duplicate]
(5 answers)
Closed 1 year ago.
I'm attempting to make a GUI for my text game (similar to a pokemom game)
In summary the code works like:
import random
hp = 100
for i in range (0,4):
element = input("Enter attack: ")
list.append(element)
attack1 = list[0]
attack2 = list[1]
attack3 = list[2]
attack4 = list[3]
while(True):
cmd = input(">")
If cmd.lower() == attack1 ... :
if cmd.lower() == bite:
hp -= 10
Now I tried doing a gui on Tkinter through buttons but it seems I can't get a grasp of it
from tkinter import *
#4 buttons
bite = 0
root = Tk()
def click(hp):
hp -= 10
myLabel = Label(text=f"{hp} hp remaining left.")
myLabel.grid(row = 5, column = 5)
def click2():
bite = 0
hp = 50
hp -= 20
myLabel = Label(text=f"{hp} hp remaining left.")
myLabel.grid(row = 5, column = 5)
bite += 1
myButton = Button(root, text=f"hello {bite}/5", command = click(hp))
myButton2 = Button(root, text=f"Presssss {bite}/5", command = click2)
myButton3 = Button(root, text="Presssss")
myButton4 = Button(root, text="Presssss")
myButton.grid(row = 0, column = 1)
myButton2.grid(row = 1, column = 1)
myButton3.grid(row = 1, column = 2)
myButton4.grid(row = 0, column = 2)
root.mainloop()
And this just presents a constant value "90, 30" due to the variables being included on the function, but whenever I'm trying to put it into an argument like
hp = 100
def click(hp):
hp -= 10
button1 = Button(root, text = "try", command = click(100))
It just returns the value 90, 30 way before the button is clicked. When hp is used as an arg, it is saying undefined.
It does so because click() function is called as soon as window is created.
To prevent it you can use lambda :
myButton = Button(root, text=f"hello {bite}/5", command = lambda: click(hp))

how do I change my counter's speed on tkinter?

I would like to make a money counter with a input box that changes the speed of the counter to display the inputed amount of money per hour, however it's very choppy and doesn't seem to work with different numbers. any advice?
import tkinter as tk
root = tk.Tk()
money = 0
money_per_hour = 1000
root.minsize(500,300)
def monies():
global money_per_hour
box = spinbox.get()
box = int(box)
final = 3600/box
final = round(final)
final = final * 1000
money_per_hour = final
countup()
button = tk.Button(text = "show me the money", fg = "green", command = monies)
button.pack(side = "bottom")
spinbox = tk.Spinbox(from_=0, to=1000000, width=5)
spinbox.pack(side = "bottom")
label = tk.Label(root, text = "$" + str(money), foreground = "green", font = ('calibri', 40, 'bold'))
label.pack()
def countup():
global money
money += 1
label['text'] = "$" + str(money)
root.after(money_per_hour, countup)
root.after(money_per_hour, countup)
root.mainloop()

Python 2 Tkinter make labels fixed/stationary

I've a Tkinter-programm where I regularly (10 times/second) update Labels with certain sensor-values.
The problem is that they are arranged with .grid right next to each other and when a value gets/loses a place (e.g. 10 -> 9, 60 -> 150, you see the number needs extra space) the label jumps back and forth (because the number gains or loses a space and therefore .grid responds by adjusting the Label).
How can i avoid that? Do I need to change Text & Numbers to a certain font or is there a function that fixes the Labels place? I'd be happy about useful answers.
Here's a code example (please notice how the labels are adjusting cause that's the problem):
#!/usr/bin/env
import sys
import time
import subprocess
from Tkinter import *
import numpy
import random
i = 0
x = 0
def GetValue():
x = random.randint(0,10000)
time.sleep(0.1)
return x
def UebergabeTkinter():
while 1:
CompleteValue = GetValue()
Variable1.set(CompleteValue)
Variable2.set(CompleteValue)
Variable3.set(CompleteValue)
Variable4.set(CompleteValue)
root.update()
def Exit():
root.destroy()
return
try:
root = Tk()
Leiste = Menu(root)
root.config(menu = Leiste)
DateiMenu = Menu(Leiste)
Leiste.add_cascade(label = "datei", menu = DateiMenu)
DateiMenu.add_command(label = "Exit", command = Exit)
EditMenu = Menu(Leiste)
Leiste.add_cascade(label = "edit", menu = EditMenu)
Variable1 = IntVar()
Variable2 = IntVar()
Variable3 = IntVar()
Variable4 = IntVar()
Ausgang = 0
for column in range(0,8,2):
String1 = "Ausgang "
String1 += `Ausgang`
Ausgang = Ausgang + 1
Label(text = String1).grid(row=0,column=column)
Ausgang = 0
for column in range(0,8,2):
String1 = "Der Wert von "
String2 = " ist: "
String1 += `Ausgang`
Ausgang = Ausgang + 1
String3 = String1+String2
Label(text = String3).grid(row=2,column=column)
Label1 = Label(root, textvariable = Variable1)
Label1.grid(row = 2, column = 1, sticky = W+E+N+S)
Label2 = Label(root, textvariable = Variable2)
Label2.grid(row = 2, column = 3, sticky = W+E+N+S)
Label3 = Label(root, textvariable = Variable3)
Label3.grid(row = 2, column = 5, sticky = W+E+N+S)
Label4 = Label(root, textvariable = Variable4)
Label4.grid(row = 2, column = 7, sticky = W+E+N+S)
UebergabeTkinter()
root.mainloop()
except KeyboardInterrupt:
print "Hallo"
You can give labels a fixed width:
Label1 = Label(root, textvariable=Variable1, width=4)
Just make sure they are large enough to fit every number that could be put in, since of course next no the label not shrinking when the number is shorter, this also means that they will not grow to fit larger numbers.

How to update a label in Tkinter, StringVar() not working

I am working on this short code that compares the single characters of two strings. After the first running, when I change the strings in the entryBoxes,I would like to replace the label created before, instead of creating a new one. I have already tried with StringVar() but it seems not working. (If it can be useful I'm using Python 2.7.6). Could you please give me a hint?
from Tkinter import *
app = Tk()
app.geometry('450x300')
labelTF = Label(app, text="Insert sequence of TF").pack()
eTF = Entry(app, width=50)
eTF.pack()
eTF.focus_set()
labelSpazio = Label(app, text="\n").pack()
labelResultedSequence = Label(app, text="Insert sequence of ResultedSequence").pack()
eResultedSequence = Entry(app, width=50)
eResultedSequence.pack()
eResultedSequence.focus_set()
def prova():
count = 0
uno = eTF.get().lower()
due = eResultedSequence.get().lower()
if len(uno)==len(due):
for i in range(0,len(uno)):
if uno[i] == due[i]:
if uno[i] in ("a", "c","g","t"):
count = count + 1
if uno[i] == "r" and due[i] in ("a", "g"):
count = count + 1
if uno[i] == "y" and due[i] in ("t", "c"):
count = count + 1
percentage = int(float(count)/float(len(uno))*100)
labelSpazio = Label(app, text="\n").pack()
mlabel3=Label(app,text= "The final similarity percentage is: "+(str(percentage) + " %")).pack()
if len(uno)!=len(due):
mlabel2 = Label(app,text="The length of the sequences should be the same").pack()
b = Button(app, text="get", width=10, command=prova)
b.pack()
mainloop()
Create the labels only once outside of the for loop and use a StringVar to modify its value. It would look like this:
# initialization
app = Tk()
label3text = StringVar()
mlabel3 = Label(app, textvariable=label3text, width=100)
mlabel3.pack()
Then in the for loop inside your function:
label3text.set("The final similarity percentage is: "+(str(percentage) + " %"))

Categories