How do you update a variable when using a button in tkinter? - python

I am writing a simple game where when the 'calculate' button is clicked, it performs the necessary calculations and displays a messagebox to the user. The user can then keep playing. However, the variable that keeps track of the money the user has, 'starting', does not update each time the button is clicked and it uses the starting value of 1000. How can I have it update? Thank you!
starting = 1000
#calculation procedure
def calculate(starting):
dice1 = random.randrange(1,7)
get_bet_entry=float(bet_entry.get())
get_roll_entry = float(roll_entry.get())
if dice1 == get_roll_entry:
starting = starting + get_bet_entry
messagebox.showinfo("Answer","You won! Your new total is $" + str(starting))
return(starting)
else:
starting = starting - get_bet_entry
messagebox.showinfo("Answer","You are wrong, the number was " + str(dice1) + '. You have $' + str(starting))
return(starting)
#designing bet button
B2 = Button(root,text = "Bet", padx=50, command = lambda: calculate(starting))

You can declare starting as a global variable inside your calculate function, so it gets updated in the global scope.
You could also make "starting" part of a mutable object if you want to avoid globals.

You shouldn't return a value from button's callback since it doesn't have a variable to return.
You can either use global to update your variable within a method or use IntVar(). I would suggest using IntVar().
starting = IntVar(root)
starting.set(1000)
def calculate():
#calculations
starting.set(calculation_result)
messagebox.showinfo("Answer","You won! Your new total is $" + str(starting.get()))
B2 = Button(......, command = calculate)
If you really want to use global,
starting = 1000
def calculate():
global starting
#calculations
starting = calculation_result
B2 = Button(......, command = calculate)
Note that in both approaches, you don't need to pass starting as parameter to your method.

Related

Cannot figure out how to finish hangman date signing

display a double 3 time method for tracking analysis with frameworks
we need to find the x for y
and describe why it happeneds that way
do not quote for 32 x 8. Most of the If the player guess a letter which exists in the word, the script writes it in all its correct positions. The player has 10 turns to guess the word. You can easily customize the game by changing the variables.live coding demo portion of the course and showing the process of coding a
#importing the time module
import time
#welcoming the user
name = raw_input("What is your name? ")
print "Hello, " + name, "Time to play hangman!"
print "
"
#wait for 1 second
time.sleep(1)
print "Start guessing..."
time.sleep(0.5)
#here we set the secret
word = "secret"
#creates an variable with an empty value
guesses = ''
#determine the number of turns
turns = 10
# Create a while loop
#check if the turns are more than zero
while turns > 0:
# make a counter that starts with zero
failed = 0
# for every character in secret_word
for char in word:
# see if the character is in the players guess
if char in guesses:
# print then out the character
print char,
else:
# if not found, print a dash
print "_",
# and increase the failed counter with one
failed += 1
# if failed is equal to zero
# print You Won
if failed == 0:
print "
You won"
# exit the script
break
print
# ask the user go guess a character
guess = raw_input("guess a character:")
# set the players guess to guesses
guesses += guess
# if the guess is not found in the secret word
if guess not in word:
# turns counter decreases with 1 (now 9)
turns -= 1
# print wrong
print "Wrong
"
# how many turns are left
print "You have", + turns, 'more guesses'
# if the turns are equal to zero
if turns == 0:
# print "You Lose"
print "You Lose
"
The mainloop is a function of the root window, so you should assign a name to it:
if __name__ == '__main__':
url = 'https://api.exchangerate-api.com/v4/latest/USD'
converter = MikesMagicalConverter(url)
app = App(converter) # Assing a name to root window
app.mainloop() # Run root window mainloop
When you create the button you should provide a reference to the master:
buttonExample = tk.Button(self, # Provide reference to master
text="Create new window",
command=lambda:self.currency_converter.createNewWindow(self)) # Pass reference
buttonExample.pack()
The command argument is a bit trickier; the class MikesMagicalConverter is not a widget and does not inherit from tkiner so you'll have to pass a reference to use as master to the Toplevel window.
You must provide a self parameter to the createNewWindow() method.
def createNewWindow(self, master):
newWindow = tk.Toplevel(master) # Using reference as master
labelExample = tk.Label(newWindow, text = "New Window")
buttonExample = tk.Button(newWindow, text = "New Window button")
labelExample.pack()
buttonExample.pack()
In general: many of your lines are way to long, makes the code hard to read.
With those changes the code will still generate error, but the button and Toplevel window pops up. I'm thinking you might rather separate the currency calculations from the GUI code.

Is it possible to use a variable then later redefine it?

I´m making a project for school and it is a dice game. This snippet of my code is like a catch 22.
I need to define a variable otherwise it flags, so I do this but then every time the button is run it changes the value to zero instead of increasing it.
if Rollnop1 == 0 :
Userscore1 = Randomnumber
print ("User 1 ",Userscore1 )
Rollnop1 = Rollnop1+1 #But this changes it so it will go to the next players roll, every
#time the button is pressed it changes the variable back to 0
def gamerun():
global Player
global usernamestr
global passwordstr
global usernamestr2
global passwordstr2
Rollnop1 = 0
def roll2():
Rollnop2 = 0
Randomnumber = random.randint(2,12)
print ("Console: Random Number 2 = ",Randomnumber)
if Rollnop2 == 0 :
Userscore2 = Randomnumber
print ("User 2 ",Userscore2 )
def roll1():
Rollnop1 = 0 #Need to define this here otherwise It wont work
Randomnumber = random.randint(2,12)
print ("Console: Random Number = ",Randomnumber)
if Rollnop1 == 0 :
Userscore1 = Randomnumber
print ("User 1 ",Userscore1 )
Rollnop1 = Rollnop1+1 #But this changes it so it will go to the next players roll, every
#time the button is pressed it changes the variable back to 0
else:
roll2()
actdicegame = Tk()
gamerunl0 = Label(actdicegame, text = usernamestr, fg = "black")
gamerunl0.pack()
gamerunl1 = Label(actdicegame, text = "Roll The Dice", fg = "black")
gamerunl1.pack()
gamerunb1 = Button(actdicegame, text="ROLL",fg="Black", command=roll1)#Register Butto
gamerunb1.pack()
actdicegame.geometry("350x500")
print ("Console: GUI RUNNING 1")
actdicegame.mainloop()
snippet https://pastebin.com/FSWwBGpA
Use an option where you provide the player as part of the roll, that way you say which player is playing at any given time. The function below plays for the provided player and returns who is playing next
def roll(Rollnop=0):
UserScore = random.randint(2,12)
print ("Console: Random Number 2 = ", UserScore)
if Rollnop == 0 :
print ("User 1 ", UserScore)
return 1
else:
print ("User 2 ", UserScore)
return 0
This could answer your question: nested function change variable in an outside function not working. Basically you need to assign Rollnop1 = 0 and Rollnop2 = 0 in gamerun and declare them as nonlocal inside roll1 & roll2 before attempting to change their value.
– DarrylG Thank You so much and to everyone else who helped.
More here
nested function change variable in an outside function not working

Increment everytime i press + button

I'm working on this Incrementor Decrementor program .. where First i enter a number and as i press + the entered number is incremented by 1 and decrements when i press - ... The problem is the value is getting incremented or decremented only once.
from tkinter import *
#******* Functions code ********
def add(event):
a=float(enter.get())
b=a+1
labelresult=Label(root,text="Result : %2f"%b).grid(row=3,column=1)
return
def sub(event):
a=float(enter.get())
b=a-1
labelresult=Label(root,text="Result : %2f"%b).grid(row=3,column=1)
return
#******* GUI code***********
root=Tk()
root.geometry('250x250')
root.title('Incrementor or Decrementor')
enter=IntVar()
label=Label(root,text="Skz.inc",bg='skyblue',fg='red').grid(row=0,column=1)
label=Label(root,text="enter a number").grid(row=1)
entry_1=Entry(root,textvariable=enter).grid(row=1,column=1)
button1=Button(root,text='+')
button1.grid(row=2,column=0)
button1.bind('<Button-1>',add)
button2=Button(root,text='-')
button2.grid(row=2,column=3)
button2.bind('<Button-1>',sub)
root.mainloop()
So the value which i entered should be increment or decrement each time i press either + or - button .
Example - when i enter 9 and press + the result should be 10 (works in my program) . Again on pressing + button the result should be 11 which is not the case in my code.
Help me out guys .. do modify and send me back the code.
Thanks
Each time you press + or - the function reads the value in the entry. You will have to update the value in the entry for every add or sub.
def add(event):
a=float(enter.get())
b=a+1
labelresult.config(text="Result : %2f"%b) # Update labelresult instead of
# creating a new label every time
enter.set(b) # Set entry to the new value
return
You will have to create labelresult in the GUI code:
labelresult = Label(root)
labelresult.grid(row=3,column=1)

Command function for button "resets"

So in my tkinter python program I am calling on a command when a button is clicked. When that happens it runs a function but in the function I have it set a label to something on the first time the button is clicked and after that it should only update the said label. Basically after the attempt it changes the attempt to 1 ensuring the if statement will see that and not allow it to pass. However it keeps resetting and I don't know how to stop it. When you click the button no matter first or third the button resets and proof of that occurs because the h gets printed. It's as if the function restarts but it shouldn't since it's a loop for the GUI.
def fight(): #Sees which one is stronger if user is stronger he gets win if no he gets loss also displays enemy stats and removes used characters after round is finished
try:
attempt=0
namel = ""
namer=""
left = lbox.curselection()[0]
right = rbox.curselection()[0]
totalleft = 0
totalright = 0
if left == 0:
namel = "Rash"
totalleft = Rash.total
elif left==1:
namel = "Untss"
totalleft = Untss.total
elif left==2:
namel = "Illora"
totalleft = 60+35+80
if right == 0:
namer = "Zys"
totalright = Zys.total
elif right==1:
namer = "Eentha"
totalright = Eentha.total
elif right==2:
namer = "Dant"
totalright = Dant.total
lbox.delete(lbox.curselection()[0])
rbox.delete(rbox.curselection()[0])
print(namel)
print(namer)
if attempt == 0:
wins.set("Wins")
loss.set("Loss")
print("h")
attempt=1
if (totalleft>totalright):
wins.set(wins.get()+"\n"+namel)
loss.set(loss.get()+"\n"+namer)
else:
wins.set(wins.get()+"\n"+namer)
loss.set(loss.get()+"\n"+namel)
except IndexError:
pass
Also for those of you who saw my previous question I still need help with that I just also want to fix this bug too.
At beginning of function fight you set attempt = 0 so you reset it.
Besides attempt is local variable. It is created when you execute function fight and it is deleted when you leave function fight. You have to use global variable (or global IntVar)
attempt = 0
def fight():
global attempt
BTW: of you use only values 0/1 in attempt then you can use True/False.
attempt = False
def fight():
global attempt
...
if not attempt:
attempt = True

Update turtle/gui while waiting for input python

I'm making a chat program, but I have run across a problem: the screen only updates after input. I'm using turtle to show the chat (I know, turtle isn't really that good for this purpose, but it's very simple.)
This is the code in my loop:
while True:
ind = userlist.index(user)
if statlist[ind] == 'banned':
print('You have been banned.')
break
word = input('>>> ')
command(word)
if word != '':
chat = user + '(' + status + '): ' + word
update_room(chat)
refresh()
Pretty much everything can be ignored here, except the
word = input('>>> ')
and
refresh()
The refresh() is what updates the turtle room.
How could I make it so that it would print out new chat, even as the user is typing? Would 2 side-by-side while loops work?
I acknowledge that my program isn't that well organized and that to fix this I will probably have to rewrite this loop.
Note: I'd rather not import anything, but if an import is needed then it would be great if that module came preloaded with python.
Or another question: Is it possible to have 2 infinite while loops running side by side at the same time?
So I'm pretty new at python but I have an idea that will just be extremely repetitive. You need to first remove the input part and make a ton of functions like this:
def key_a:
global key_in
key_in = key_in + 'a'
def key_b:
global key_in
key_in = key_in + 'b'
def key_c:
global key_in
key_in = key_in + 'c'
Have it so if your input is enter, then it will set it to the word and reset the input variable.
def key_enter:
global key_in
global word
word = key_in
key_in = ''
Then bind your inputs (think of "win" as your window variable.)
win.listen()
win.onkeypress(key_a, 'a')
Also do the same for capital letters.
win.onkeypress(caps_key_a, 'A')
Please tell me if this helps.
Here's an improvement on TaCo's answer suggesting onkeypress which enables real-time typed user input so you can re-render even if the user is holding down keys.
My contribution is to use a loop that calls a general function so there's no need to manually create a separate function per key. I've also provided a minimal, runnable example which should be easily adaptable to a chat interface, typing game or other context.
I haven't attempted to handle every key and edge case, so you might want to dig into the list of Tk keys and make sure it works for your needs. Feel free to suggest an improvement if you encounter any odd behavior.
import turtle
from datetime import datetime
def tick():
current_time = datetime.now().strftime("%H:%M:%S")
turtle.clear()
turtle.goto(0, 50)
turtle.write(current_time, align="center", font=font)
turtle.goto(0, -50)
turtle.write(f"'{text}'", align="center", font=font)
turtle.update()
turtle.Screen().ontimer(tick, 1000 // 30)
def handle_keypress(key):
global text
text += key
def handle_backspace():
global text
text = text[:-1]
def add_key_handler(key):
turtle.Screen().onkeypress(lambda: handle_keypress(key), key)
font = "Courier New", 18, "normal"
text = ""
turtle.tracer(0)
turtle.penup()
turtle.hideturtle()
for i in range(33, 122):
if i != 45:
add_key_handler(chr(i))
turtle.Screen().onkeypress(handle_backspace, "BackSpace")
turtle.Screen().onkeypress(lambda: handle_keypress(" "), "space")
turtle.Screen().onkeypress(lambda: handle_keypress("-"), "minus")
turtle.listen()
tick()
turtle.exitonclick()
Reference: Is there a complete list of key event names used by turtle-graphics?

Categories