Python Tkinter Def change Var [duplicate] - python

This question already has answers here:
Short description of the scoping rules?
(9 answers)
Closed 7 years ago.
I am still learning Tkinter and I am trying to make a simple programe that on a button click will gen three random nums but the def will not change the var, it will print it to the console but will not change the vars
from tkinter import *
import random
firstNum = 0
secondNum = 0
thirdNum = 0
def PickNewNums():
firstNum = random.randint(1, 100)
secondNum = random.randint(1, 100)
thirdNum = random.randint(1, 100)
print(firstNum)
return firstNum, secondNum, thirdNum
root = Tk()
mainTitle = Label (root, text = "Amazing Title")
newNumbers = Button(root, text = "Get New Numbers", command=PickNewNums)
firstNumber = Label(root, text = firstNum)
secondNumber = Label(root, text = secondNum)
thirdNumber = Label(root, text = thirdNum)
mainTitle.pack()
firstNumber.pack()
secondNumber.pack()
thirdNumber.pack()
newNumbers.pack(side = BOTTOM)
root.geometry("600x300")
root.mainloop()
Thanks for any help here guys!

I would prefer wrapping things in a class.
You can associate a Tkinter variable with a label. When the contents of the variable changes, the label is automatically updated:
v = StringVar()
Label(root, textvariable=v).pack()
To update do :
v.set("Hest!")

Related

How to make a button create a label and shortly after that hide in tkinter

My code:
def Click():
global output
output = StringVar()
output = random.randint(1, 6)
global outputL
outputL = Label(root, text = f"The number is... {output}")
outputL.pack()
output = 0
How do I make it hide the label after that?
Use after method and config method
(TIP) Don't create a widgets(Labels, Buttons, etc...) inside a function. Use config method to update your widgets
from tkinter import *
import random
root = Tk()
def Remove_Output():
outputL.pack_forget()
def click():
global output
output = StringVar()
output = random.randint(1, 6)
outputL.config(text=f"The number is... {output}")
outputL.pack()
output = 0
root.after(1000, Remove_Output)
btn = Button(root, text="Click",command=click)
btn.pack()
outputL = Label(root, text = "")
root.mainloop()

Tkinter window crashes when clicked, probably due to infinite loop. Python 3.7.1

I'm trying to create a programm that reads ANT signals and displays them in a TKinter window.
To display the changing values, I'm updating labels (in an infinite loop),which works so far, but whenever I try to move the window, the program crashes (no response).
So here's what the (final program) should do:
Receive and store the ANT data, which I read with another file (which gives me
power and cadence)
Round the numbers to 2-3 decimals (max)
Read the total power output so far from a file
Write the power data in a file (append)
Sum the total power output
display the current speed, cadence, power and total power output
My Code:
# imports
import random
import time
from tkinter import *
# creating root tkinter Window
root = Tk()
root.title("ANT+ Live Data")
# defining Text Variables
running = 0
SAVE_FILE = "power_doc.txt"
HEADLINE_TEXT = StringVar()
HEADLINE_TEXT.set('')
HEADLINE_M = StringVar()
HEADLINE_M.set('')
power_display = StringVar()
power_display.set('0')
cadence_display = StringVar()
cadence_display.set('0')
speed_display = StringVar()
speed_display.set('0')
powertotal_display = StringVar()
powertotal_display.set('0')
# defining Window Size
root.geometry("800x600")
# creating Label Frame to wrap labels
frame = LabelFrame(root)
frame.pack(padx=20, pady=20)
# creating labels, Headline 1
slabel = Label(root, font = ("Helvetica",48) ,textvariable = HEADLINE_M, justify=CENTER, bg="#FFFFFF", fg = '#000000')
slabel.pack(fill=BOTH, padx=20, pady=10)
# headline 2
headLine = Label(root, font=("Helvetica", 26), textvariable= HEADLINE_TEXT, justify=CENTER, bg="#FFFFFF", fg = '#000000')
headLine.pack(fill=BOTH, pady=5)
# power
l1 = Label(root, font = ("Helvetica",20) ,textvariable = power_display, justify=CENTER, bg="#190000", fg = '#B0C4C2')
l1.pack(fill=BOTH)
# cadence
l2 = Label(root, font = ("Helvetica",20), textvariable = cadence_display, justify=CENTER, bg="#190000", fg = '#B0C4C2')
l2.pack(fill=BOTH)
# speed
l3 = Label(root, font = ("Helvetica",20), textvariable = speed_display, justify=CENTER, bg="#190000", fg = '#B0C4C2')
l3.pack(fill=BOTH)
# total Power
l4 = Label(root, font = ("Helvetica",20), textvariable = powertotal_display, justify=CENTER, bg="#190000", fg = '#B0C4C2')
l4.pack(fill=BOTH)
# function to read total power values out of a file
def get_power_total(SAVE_FILE):
power_total = 0
with open(SAVE_FILE, 'r') as inp:
for line in inp:
try:
num = float(line)
power_total += num
except ValueError:
print('{} is not a number!'.format(line))
power_total = round_number(power_total)
return power_total
# generate random Numbers for testing purposes
def randomize_number(inputNumber):
inputNumber = float(inputNumber)*random.uniform(0.99, 1.01)
inputNumber = round_number(inputNumber)
return inputNumber
# rounds numbers to 2 decimals
def round_number(inputNumber):
inputNumber = round(inputNumber, 2)
return inputNumber
# use formula for a 28" Wheel to determine Speed using cadence
def determine_speed(cadence):
speed = float(cadence)*0.356
speed = round_number(speed)
return speed
def get_power(cadence):
power = float(cadence)*0.8
power = round_number(power)
return power
# dummy function to test-print Values, redundant in current state
def print_values(x1, x2, x3):
print("Leistung: {} W Trittfrequenz: {} Geschwindigkeit: {} Km/H" .format(x1, x2, x3))
# write in document to determine total power output
def write_file(SAVE_FILE, power):
f = open(SAVE_FILE, "a+")
f.write(str(power) + '\n')
f.close()
def update_label():
power_total = get_power_total(SAVE_FILE)
cadence = int(50)
cadence = randomize_number(cadence)
root.after(100)
power = get_power(cadence)
root.after(100)
speed = determine_speed(cadence)
root.after(100)
power_total += power
write_file(SAVE_FILE, power)
power_display.set("Leistung: {} W".format(power))
cadence_display.set("Trittfrequenz: {}".format(cadence))
speed_display.set("Geschwindigkeit : {} Km/h".format(speed))
powertotal_display.set("Gesamtleistung seit 10 Uhr: {} W".format(power_total))
root.after(1000)
root.update_idletasks()
# mainloop to display the window
while True:
root.after(1000, update_label())
root.mainloop()
This is basically just a draft to import the ANT data, hence there are some numbers being randomly generated to show if the label update function works.
I'm fairly new to coding with Python (or coding at all), so I'm pretty sure there are other issues with my code as well, but perhaps someone has a suggestion on how to solve my issue.
Any help or suggestions are appreciated.
Cheers in advance!
Edit: Solved! thanks Jason!
Changes were to be made here:
def update_label():
power_display.set("Leistung: {} W".format(power))
cadence_display.set("Trittfrequenz: {}".format(cadence))
speed_display.set("Geschwindigkeit : {} Km/h".format(speed))
powertotal_display.set("Gesamtleistung seit 10 Uhr: {} W".format(power_total))
root.after(1000, update_label)
root.update_idletasks()
root.after(1000, update_label)
root.mainloop()

Python: Tkinter stopping due to while loop

I am trying to run a while loop inside my program, but when the while loop is in place, the code stops, and the tkinter window does not open. How do I solve this? It should be so that the code writes out two random numbers, and then when the correct answer is input, it should re-loop.
from tkinter import *
import random
root = Tk()
#Frames
topFrame = Frame(root) # I want an invisible container in root
topFrame.pack()
bottomFrame = Frame(root) # I want an invisible container in root
bottomFrame.pack(side=BOTTOM)
#End Of Frames
#Addition Question Maker
AnswerBox = Entry(topFrame)
AnswerBox.grid(row=0,column=4)
EqualsSign = Label(topFrame, text="=").grid(row=0,column=3)
AdditionSign = Label(topFrame, text="+").grid(row=0,column=1)
NewQuestion = True
while NewQuestion == True:
AdditionQuestionLeftSide = random.randint(0, 10)
AdditionQuestionRightSide = random.randint(0, 10)
global Total
Total = AdditionQuestionLeftSide + AdditionQuestionRightSide
AdditionQuestionRightSide = Label(topFrame, text= AdditionQuestionRightSide).grid(row=0,column=0)
AdditionQuestionLeftSide= Label(topFrame, text= AdditionQuestionLeftSide).grid(row=0,column=2)
answer = None
def OutputAnswerText(event):
global answer
answer = AnswerBox.get()
if Total == int(answer):
Correct = Label(topFrame, text="Correct").grid(row=2,column=3)
NewQuestion = True
else:
Correct = Label(topFrame, text="Wrong").grid(row=2,column=3)
AnswerBox.bind('<Return>', OutputAnswerText)
root.mainloop()
Instead of making a while loop, I suggest making NewQuestion a function. The function gets called initially, then if the answer is correct the function gets called again. Here is my code for the function, along with an automatic entry delete option to remove the need to backspace your answer after inputting a correct answer.
from tkinter import *
import random
root = Tk()
#Frames
topFrame = Frame(root) # I want an invisible container in root
topFrame.pack()
bottomFrame = Frame(root) # I want an invisible container in root
bottomFrame.pack(side=BOTTOM)
#End Of Frames
#Addition Question Maker
AnswerBox = Entry(topFrame)
AnswerBox.grid(row=0,column=4)
EqualsSign = Label(topFrame, text="=").grid(row=0,column=3)
AdditionSign = Label(topFrame, text="+").grid(row=0,column=1)
def NewQuestion():
AdditionQuestionLeftSide = random.randint(0, 10)
AdditionQuestionRightSide = random.randint(0, 10)
global Total
Total = AdditionQuestionLeftSide + AdditionQuestionRightSide
AdditionQuestionRightSide = Label(topFrame, text= AdditionQuestionRightSide).grid(row=0,column=0)
AdditionQuestionLeftSide= Label(topFrame, text= AdditionQuestionLeftSide).grid(row=0,column=2)
answer = None
return
NewQuestion()
def OutputAnswerText(event):
global answer
global AnswerBox
answer = AnswerBox.get()
if Total == int(answer):
Correct = Label(topFrame, text="Correct").grid(row=2,column=3)
AnswerBox.delete(0, END)
NewQuestion()
else:
Correct = Label(topFrame, text="Wrong").grid(row=2,column=3)
AnswerBox.bind('<Return>', OutputAnswerText)
root.mainloop()
You have an infinite loop:
while NewQuestion == True:
There is no place where NewQuestion can become false (and no break in the loop). So the loop is infinite.
Also:
EqualsSign = Label(topFrame, text="=").grid(row=0,column=3)
doesn't work because grid returns None. If you want to keep a reference to the widget, you have to use the two-lines version like in:
AnswerBox = Entry(topFrame)
AnswerBox.grid(row=0,column=4)

Python, Tkinter a mathgame how to make a point-system

I'm on a simple project to make a math game. So far everything good, the user can choose to multiply or add. Then recives a multiplication to solve or a addition, then is give feedback. But I wish to extend my game, I want to make some kind of count/Highscore but not complicated only to give the user feedback in the simplest way, like if they get 5 answers correct in a row it will say in a text-box "Congratulations you've got 5 points". I'm not sure how to go further on with this project, simply I want it to be a python math-game made in Tkinter with a count function for each correct answer.
I'm using Tkinter & Python 2.7 for this, further on I wish to make a tutorial on this project to post on youtube. And all help is very very appreciated.
from Tkinter import *
import tkMessageBox
import random
import time
def fraga():
global num1
num1 = random.randint(1, 100)
global num2
num2 = random.randint(1, 100)
global svar
svar = num1 + num2
label1.config(text='Vad blir ' + str(num1) + '+' + str(num2) + '?')
entry1.focus_set()
def fraga1():
global num3
num3 = random.randint(1, 10)
global num4
num4 = random.randint(1, 10)
global svar1
svar1 = num3 * num4
label1.config(text='Vad blir ' + str(num3) + '*' + str(num4) + '?')
entry1.focus_set()
def svar1():
mainAnswer = entry1.get()
# feedback på tom ruta
if len(mainAnswer) == 0:
tkMessageBox.showwarning(message='Skriv in några nummer!')
return
if int(mainAnswer) != svar1:
tkMessageBox.showwarning(message='Tyvärr det rätta svaret: ' + str(svar1))
else:
tkMessageBox.showinfo(message='RÄTT!! :)')
def svar():
mainAnswer = entry1.get()
# feedback på tom ruta
if len(mainAnswer) == 0:
tkMessageBox.showwarning(message='Skriv in några nummer!')
return
if int(mainAnswer) != svar:
tkMessageBox.showwarning(message='Tyvärr det rätta svaret: ' + str(svar))
else:
tkMessageBox.showinfo(message='RÄTT!! :)')
def quit():
global root
root.destroy()
#fönster
root = Tk()
root.title("Andrejs mattespel Quiz")
root.geometry('700x700')
# välkomstmeddelande
label2 = Label(root, text="Hej!\n Nu ska vi lösa lite matteproblem!")
label2.config(font=('times', 18, 'bold'), fg='black', bg='white')
label2.grid(row=0, column=0)
#labels
label1 = Label(root)
label1.grid(row=2, column=0)
#start
entry1 = Entry(root)
entry1.grid(row=3, column=0)
# Omstartknappen
entry1.bind('<Return>', func=lambda e:checkAnswer())
#Knappar
fragaBtn = Button(root, text='Jag vill öva på addition!', command=fraga)
fragaBtn.grid(row=4, column=0)
svarButton = Button(root, text='Svar addition', command=svar)
svarButton.grid(row=4, column=1)
quit_bttn = Button(root, text = "Avsluta", command=quit)
quit_bttn.grid(row = 4, column = 3, sticky = W)
#Knappar multiplikation
Make a score variable and increment by 1 each time the user is right.
Now make a list named highscores. This should give you the idea of what to do:
#when user looses
if score > highscores[-1]:
highscores[-1] = score
highscores.sort()
#Then display a list of best results with the current result marked or something :)
If you want to save scores, you need to write them to a file. The easiest ways to do so would be the json module. Just json.dump(highscores, open(path, 'w')) to save and highscores = json.load(open(path)) to reload from the file would do when dealing with lists and dicts.

Tkinter Math Quiz

What is wrong with this program? Every time I run it the first math problem is show before I push start. Also the answer is always the first math problem, it never changes. Also there should not be a math problem above the timer. Thanks, Scott
from Tkinter import*
import time
import tkMessageBox
import random
def Questions():
number1 = random.randrange(1,25)
number2 = random.randrange(1,50)
answer = number1 + number2
prompt = ("Add " + str(number1) + " and " + str(number2))
label1 = Label(root, text=prompt, width=len(prompt), bg='yellow')
label1.pack()
return answer
def start():
global count_flag
Questions()
count_flag = True
count = 0.0
while True:
if count_flag == False:
break
# put the count value into the label
label['text'] = str(count)
# wait for 0.1 seconds
time.sleep(0.1)
# needed with time.sleep()
root.update()
# increase count
count += 0.1
def Submit(answer, entryWidget):
""" Display the Entry text value. """
global count_flag
count_flag = False
print answer
if entryWidget.get().strip() == "":
tkMessageBox.showerror("Tkinter Entry Widget", "Please enter a number.")
if answer != int(entryWidget.get().strip()):
tkMessageBox.showinfo("Answer", "INCORRECT!")
else:
tkMessageBox.showinfo("Answer", "CORRECT!")
# create a Tkinter window
root = Tk()
root.title("Math Quiz")
root["padx"] = 40
root["pady"] = 20
# Create a text frame to hold the text Label and the Entry widget
textFrame = Frame(root)
#Create a Label in textFrame
entryLabel = Label(textFrame)
entryLabel["text"] = "Answer:"
entryLabel.pack(side=LEFT)
# Create an Entry Widget in textFrame
entryWidget = Entry(textFrame)
entryWidget["width"] = 50
entryWidget.pack(side=LEFT)
textFrame.pack()
#directions
directions = ('Click start to begin. You will be asked a series of questions.')
instructions = Label(root, text=directions, width=len(directions), bg='orange')
instructions.pack()
# this will be a global flag
count_flag = True
answer = Questions()
Sub = lambda: Submit(answer, entryWidget)
#stopwatch = lambda: start(answer)
# create needed widgets
label = Label(root, text='0.0')
btn_submit = Button(root, text="Submit", command = Sub)
btn_start = Button(root, text="Start", command = start)
btn_submit.pack()
btn_start.pack()
label.pack()
# start the event loop
root.mainloop()
Your problem is with how you're calling the Questions() method. You only ask for the answer once with
answer = Questions()
and you do this before you press start (which is why it shows up before you hit start)
To fix it you could use code like this:
from Tkinter import*
import time
import tkMessageBox
import random
def Questions():
number1 = random.randrange(1,25)
number2 = random.randrange(1,50)
answer = number1 + number2
prompt = ("Add " + str(number1) + " and " + str(number2))
label1 = Label(root, text=prompt, width=len(prompt), bg='yellow')
label1.pack()
return answer
def start():
global count_flag
global answer
answer = Questions()
count_flag = True
count = 0.0
while True:
if count_flag == False:
break
# put the count value into the label
label['text'] = str(count)
# wait for 0.1 seconds
time.sleep(0.1)
# needed with time.sleep()
root.update()
# increase count
count += 0.1
def Submit(answer, entryWidget):
""" Display the Entry text value. """
global count_flag
count_flag = False
print answer
if entryWidget.get().strip() == "":
tkMessageBox.showerror("Tkinter Entry Widget", "Please enter a number.")
if answer != int(entryWidget.get().strip()):
tkMessageBox.showinfo("Answer", "INCORRECT!")
else:
tkMessageBox.showinfo("Answer", "CORRECT!")
# create a Tkinter window
root = Tk()
root.title("Math Quiz")
root["padx"] = 40
root["pady"] = 20
# Create a text frame to hold the text Label and the Entry widget
textFrame = Frame(root)
#Create a Label in textFrame
entryLabel = Label(textFrame)
entryLabel["text"] = "Answer:"
entryLabel.pack(side=LEFT)
# Create an Entry Widget in textFrame
entryWidget = Entry(textFrame)
entryWidget["width"] = 50
entryWidget.pack(side=LEFT)
textFrame.pack()
#directions
directions = ('Click start to begin. You will be asked a series of questions.')
instructions = Label(root, text=directions, width=len(directions), bg='orange')
instructions.pack()
# this will be a global flag
count_flag = True
Sub = lambda: Submit(answer, entryWidget)
#stopwatch = lambda: start(answer)
# create needed widgets
label = Label(root, text='0.0')
btn_submit = Button(root, text="Submit", command = Sub)
btn_start = Button(root, text="Start", command = start)
btn_submit.pack()
btn_start.pack()
label.pack()
# start the event loop
root.mainloop()
In this code the answer is updated every time you hit start and only updates when you hit start.

Categories

Resources