Tkinter update label when variable changes - python

I am working on a code that is a clicker game. I have done 90% myself as I have never used Tkinter module before so was a learning project really, anyway to the problem:
I have just sorted the auto clicking function and a label in the window attached to a variable (the amount of cash), at the moment I have the label at a .pack(), and set so it creates a new label after every second. Obviously this will create confusion and isn't what you would expect from a game, so I wondered if there was a way to either:
1) Make the label update every time the variable (Amount of cash) updates (This would be Ideal if you can help me with this)
2)Delete the label with a line of code and then put the new label in with the current variables number (Not as good as the first, but would still be great to have this one if the first isn't possible)
Here is the code so far:
import time
from tkinter import *
root=Tk()
CPS=0
cash=0
mult=1
def blankLine():
for i in range(16):
print ("")
def infoprint():
print("Cash =",cash)
print("")
print("Each click is worth",mult,"cash")
print("")
print("CPS =",CPS)
blankLine()
def CashASecond():
global root
global cash
global CPS
cash += CPS
root.after(1000, CashASecond)
CashASecond()
def CashLabel():
label1=Label(root,text=cash)
label1.pack()
root.after(1000, CashLabel)
CashLabel()
def ManualClicker():
global cash
global mult
cash += 1*(mult)
infoprint()
ManualClickerButton=Button(root,text="Click",command=ManualClicker)
ManualClickerButton.pack()
class upgrades():
def DoubleManualClicker():
global cash
global mult
if cash < 1000:
print("Not enough cash, sorry")
elif cash>= 1000:
print ("Double clicks purchased!")
mult *= 2
cash = cash - 1,000
DoubleManualClickerButton=Button(root,text="Purchase double clicks",command=DoubleManualClicker)
DoubleManualClickerButton.pack()
DoubleManualClickerLabel=Label(root,text="Each click is worth twice as much, costs 1,000 \n")
DoubleManualClickerLabel.pack()
def clicker():
global cash
global mult
global CPS
if cash < 25:
print("Not enough cash, sorry")
elif cash >=25:
CPS += 1
print("CPS is now",CPS)
cash = cash - 25
ClickerButton=Button(root,text="Purchase auto clicker", command=clicker)
ClickerButton.pack()
ClickerLabel=Label(root,text="+1 CPS, costs 25 \n")
ClickerLabel.pack()
def SingleMachine():
global cash
global mult
global CPS
if cash < 50:
print("Not enough cash, sorry")
elif cash >= 50:
CPS += 3
print("CPS is now",CPS)
cash = cash - 50
SingleMachineButton=Button(root,text="Purcahse Single Cash Printer",command=SingleMachine)
SingleMachineButton.pack()
SingleMachineLabel=Label(root,text="+3 CPS, costs 50 \n")
SingleMachineLabel.pack()
def LoftOfCashPrinter():
global cash
global mult
global CPS
if cash < 100:
print("Not enough cash, sorry")
elif cash >= 100:
CPS += 5
print("CPS is now",CPS)
cash=cash-100
LoftOfCashPrinterButton=Button(root,text="Purchase a loft of cash printers",command=LoftOfCashPrinter)
LoftOfCashPrinterButton.pack()
loftlabel=Label(root,text="+7 CPS, costs 100 \n")
loftlabel.pack()
root.title("Cash Clicker! ALPHA! By George Hill")
root.geometry("500x900+900+0")
root.mainloop()
Thanks in advance :)

I had this problem before and the way I managed to fix this was to use events and bindings. Note that I am using classes and Application. e.g.
def Click(self, event):
self.Label['text'] = ....
....
self.Buy = Button(....)
self.Buy.grid(....)
self.Buy.bind('<Button>', self.Click)
self.Label = Label(....)
self.Label.grid(....)
I understand this code is very basic (it won't work) and the use of .... is to show where the use of variables and the like will be used. This is written purely to show you how to bind widgets.

Related

How do I create a variable that can be changed by calling a function in Python but also saves the data of the past changes?

For example, let's say I'm trying to create a wallet system in python where money can be add to and taken out of. I try this code here:
balance = 0
def addmoney(x):
x += balance
addmoney(10000)
print(balance)
but it just gave me 0.
so then I tried this:
def addmoney(x):
balance = 0
balance += x
And I realized that this would set the money back to 0 every time the user adds money, which I didn't want. Is there a solution to this?
You could declare the balance variable as global inside the function.
balance = 0
def addmoney(x):
global balance
balance += x
addmoney(10000)
print(balance)
This is usually do with OOP:
class BankAccount:
def __init__(self, owner, balance, currency):
self.owner = owner
self.balance = balance
self.currency = currency
def print_balance(self):
print("Your current balance is:")
print(self.balance)
def make_deposit(self, amount):
if amount > 0:
self.balance += amount
else:
print("Please enter a valid amount.")
def make_withdrawal(self, amount):
if self.balance - amount >= 0:
self.balance -= amount
else:
print("You don't have enough funds to make this withdrawal.")
To call the function:
my_savings_account = BankAccount("Pepita Perez", 45600, "USD")
my_savings_account.print_balance()
my_savings_account.make_deposit(5000)
my_savings_account.make_withdrawal(200)
my_savings_account.print_balance()
In Python, you must use the global keyword when accessing global variables from within a function. See here.
One way to keep track of the changes is to store the previous values in a list outside the function. Again, using the global keyword
Also your logic for the balance is backwards. You should be adding x to the balance.
balance = 0
historyLst = []
def addmoney(x):
global balance
global historyLst
historyLst.append(balance)
balance += x
addmoney(10000)
print(balance)

How can i fix this with threading or multithreading

So in short im making a python game using Tkinter for some GUI, Thats not the problem.
when im running the code its freesing for 10 second. tell me how i can fix this using threading.
sorry i cant write a question properly
def timepas():
global time0
global money
global total_money
global Invests
global Invests_money
global stopInvest
global countlocal
while stopInvest:
countlocal = countlocal + 1
Invests_money = Invests * 2
money = money + Invests_money
print(money)
time.sleep(1)
if countlocal == count:
stopInvest = False
continue
def work_money():
global money
money += 1
def BankAcc():
global money
messagebox.showinfo("Your Bank Account", "You have $:" + str(total_money))
def Inves():
global Invests
global money
if money >= 10:
Invests = Invests + 1
money = money - 10
def stop_investing():
global count
global countlocal
global total_money
global money
count = 10
countlocal
total_money = total_money + money

Python while loop continues even when false (even if variable declared global)

I have a while loop in python that won't stop when false, but unlike other questions, I encountered on stack overflow, I declared my global variable.
import random
score = 0
health = 75
maxhealth = 100
keys = 0
health_potions = 0
skip_stage = 1
cmd = ""
inc = 0
def hiahelp():
#code
def stats():
#code
def oCmds():
global cmd
global inc
global health
if cmd == "stats":
stats()
inc = 0
elif cmd == "help":
hiahelp()
inc = 0
elif cmd == "use health potion":
#healing code
elif cmd == "use":
print("incomplete command")
else:
inc = 1
#intro code
while health > 0:
#more intro code
print("What is HungryIronApple's favorite music artist (besides himself, include proper capitalization)?")
def stage1():
r = True
while r:
global inc
global cmd
global health
if inc == 1:
print("incorrect, try again")
health = health - 10
cmd = input("answer: ")
if cmd == "Alan Walker":
inc = 0
r = False
elif cmd == "left" or cmd == "right":
print("originally I would take health away for such a dumb mistake but because we are just getting started, I'll ignore it")
else:
oCmds()
stage1()
print("the door opens")
quit()
print(f"you died {username}")
I expected it to stop when I die but it continues asking for answers.
Can someone please explain this?
please note I hardly use tag comments and that they are just substitutions.
Below is an example of the running code:
Your while loop is constrained by values of health. The only time health changes within your loop is if inc == 1.
Given your code snippet, it's impossible to say if inc ever changes within your loop (I do see #more code so I'm guessing there's something in there?). Since it starts at 0 and never changes, then health will never change also.
To debug this, take a look at values of inc and health and track their change over time. It may also help you to temporarily change the iteration of while health > 0 to for x in range(100) so that you constrain the repetition and can debug patterns in the change in values for health and inc.
It's pretty obvious that inc is set to 0, and then health doesn't get modified at all.
Thus, the while loop condition never breaks.
The global statement is redundant, in python a scope is limited to 3 possibilities (global, local, nonlocal).
Unlike C, where each block has its own scope.

NameError: Global Name not defined

my python code keeps getting nameerror, global variable not defined on ticketSold. I am not sure how to fix this, as I did define it as a global variable. Any help is appreciated.
aLimit=300
bLimit=500
cLimit=100
aPrice=20
bPrice=15
cPrice=10
def Main():
global ticketSold
getTickets(aLimit)
sectionIncome=calcIncome(ticketSold,aPrice)
SectionIncome+=totalIncome
print("The theater generated this much money from section A "+str(sectionIncome))
getTickets(bLimit)
sectionIncome=calcIncome(ticketSold,bPrice)
SectionIncome+=totalIncome
print("The theater generated this much money from section B "+str(sectionIncome))
getTickets(cLimit)
sectionIncome=calcIncome(ticketSold,cPrice)
sectionIncome+=totalIncome
print("The theater generated this much money from section C "+str(sectionIncome))
print("The Theater generated "+str(totalIncome)+" total in ticket sales.")
def getTickets(limit):
ticketSold=int(input("How many tickets were sold? "))
if (ticketsValid(ticketSold,limit)==True):
return ticketSold
else:
getTickets(limit)
def ticketsValid(ticketSold,limit):
while (ticketSold>limit or ticketSold<0):
print ("ERROR: There must be tickets less than "+str(limit)+" and more than 0")
return False
return True
def calcIncome(ticketSold,price):
return ticketSold*price
Saying global varname does not magically create varname for you. You have to declare ticketSold in the global namespace, for example after cPrice=10. global only makes sure that when you say ticketSold, you're using the global variable named ticketSold and not a local variable by that same name.
Here is a version which:
is Python 2 / 3 compatible
does not use any global variables
is easily extended to any number of sections
demonstrates some benefits of OOP (as opposed to a proliferation of named variables: aLimit, bLimit, etc - what will you do when you reach 27 sections?)
And so:
import sys
if sys.hexversion < 0x3000000:
# Python 2.x
inp = raw_input
else:
# Python 3.x
inp = input
def get_int(prompt):
while True:
try:
return int(inp(prompt))
except ValueError: # could not convert to int
pass
class Section:
def __init__(self, name, seats, price, sold):
self.name = name
self.seats = seats
self.price = price
self.sold = sold
def empty_seats(self):
return self.seats - self.sold
def gross_income(self):
return self.sold * self.price
def sell(self, seats):
if 0 <= seats <= self.empty_seats():
self.sold += seats
else:
raise ValueError("Cannot sell {} seats, only {} are available".format(seats, self.empty_seats))
def main():
# create the available sections
sections = [
Section("Loge", 300, 20., 0),
Section("Floor", 500, 15., 0),
Section("Wings", 100, 10., 0)
]
# get section seat sales
for section in sections:
prompt = "\nHow many seats were sold in the {} Section? ".format(section.name)
while True:
# prompt repeatedly until a valid number of seats is sold
try:
section.sell(get_int(prompt))
break
except ValueError as v:
print(v)
# report section earnings
print("The theatre earned ${:0.2f} from the {} Section".format(section.gross_income(), section.name))
# report total earnings
total_earnings = sum(section.gross_income() for section in sections)
print("\nTotal income was ${:0.2f} on ticket sales.".format(total_earnings))
if __name__=="__main__":
main()
which gives us
How many seats were sold in the Loge Section? 300
The theatre earned $6000.00 from the Loge Section
How many seats were sold in the Floor Section? 300
The theatre earned $4500.00 from the Floor Section
How many seats were sold in the Wings Section? 100
The theatre earned $1000.00 from the Wings Section
Total income was $11500.00 on ticket sales.

global name not defined error

I keep on getting an error with my discount variable. name-error: global name 'discount' not defined. please take a look at my code and help me out. I don't want to modify the parameters of the functions at all.
def finddiscount(quantity):
if quantity >= 1 and quantity <= 9:
discount = 0
elif quantity >= 10 and quantity <= 19:
discount = .2
elif quantity >= 20 and quantity <= 49:
discount = .30
elif quantity >= 50 and quantity <= 99:
discount = .40
elif quantity >= 100:
discount = .50
return discount
def calctotal(quantity, price):
finddiscount(quantity)
disc = (price*quantity)*discount
total = (price*quantity)
due = (price*quantity)-(price*quantity)*dicount
print ("\t","Order total $",format(total, "10.2"),"\n\t","Discount $",format(disc,"10.2"),"\n\t","Amount Due $",format (due, "10.2"),sep="")
def main():
quantity = int(input("How many packages where purchased?"))
price = float(input("How much is each item?"))
calctotal(quantity, price)
main()
You have to declare discount as a global if you want to access it in a multi block scope.
discount = 0
def finddiscount(quantity):
...
global discount # Needed to modify global copy of discount
discount = 1
disc = (price*quantity)*discount
You never defined discount in calctotal (and neither in global scope). Assign the result from finddiscount(quantity) to it. At the moment you are calculating the discount, but drop the result immediately by not assigning it to any variable:
def calctotal(quantity, price):
discount = finddiscount(quantity)
disc = (price*quantity)*discount
total = (price*quantity)
due = (price*quantity)-(price*quantity)*dicount
print ("\t","Order total $",format(total, "10.2"),"\n\t","Discount $",format(disc,"10.2"),"\n\t","Amount Due $",format (due, "10.2"),sep="")
If we look at this block of code
def calctotal(quantity, price):
finddiscount(quantity)
disc = (price*quantity)*discount
total = (price*quantity)
due = (price*quantity)-(price*quantity)*dicount
print ("\t","Order total $",format(total, "10.2"),"\n\t","Discount $",format(disc,"10.2"),"\n\t","Amount Due $",format (due, "10.2"),sep="")
neither discount nor dicount (I'm assuming typo) have been declared in calctotal(). Below should solve yoru issue
def calctotal(quantity, price):
discount = finddiscount(quantity)
disc = (price*quantity)*discount
total = (price*quantity)
due = (price*quantity)-(price*quantity)*discount
print ("\t","Order total $",format(total, "10.2"),"\n\t","Discount $",format(disc,"10.2"),"\n\t","Amount Due $",format (due, "10.2"),sep="")
EDIT:
While making discount a global variable is certainly a way to do this, in general I'd recommend not making a variable global unless you have a good reason. For example - if the discount applied was going to be affected by external functions, and you wanted it changed in finddiscount() as well then a global variable would work nicely. However in this scenario you are creating all possible values of discount within finddiscount() and it just makes more sense to use assignment.
The problem with global variables is that you can accidentally reassign them to things you didn't intend to do, and it can clutter up the namespace if done for no reason.

Categories