I have been trying to develop a simple checkbox scoring program.
In ideal conditions, the following code would, after confirming a robot has completed an obstacle course correctly, offer an option that should increase the score by 10 points. The second option is displayed, but the label (known as ScoreDisplay
) does not update when it is selected, remaining as 0.
What is the solution be for the issue of the ScoreDisplay
label not updating on-screen?
from tkinter import *
window = Tk()
window.geometry('600x600')
window.title("Vex Scoring")
Score = IntVar()
ObstacleBumper = IntVar()
ObstacleDistance = IntVar()
PlateuFace = IntVar()
PlateuPick = IntVar()
PlateuLED = IntVar()
ColorWheelCorrect = IntVar()
FlashGateCorrect = IntVar()
PedestalLEDCorrect = IntVar()
PedestalLEDIncorrect = IntVar()
PedestalCubeCorrect = IntVar()
PedestalCubeIncorrect = IntVar()
CorralCWCorrect = IntVar()
CorralCWIncorrect = IntVar()
BotHung = IntVar()
NoBalls = IntVar()
ScoreValues = {"ObstacleBumper":10, "ObstacleDistance":15, "PlateuFace":5, "PlateuPick":5, "PlateuLED":5, "ColorWheelCorrect":10, "FlashGateCorrect":10, "PedestalLEDCorrect":15, "PedestalLEDIncorrect":10, "PedestalCubeCorrect":10, "PedestalCubeIncorrect":5, "CorralCWCorrect":5, "CorralCWIncorrect":2, "BotHung":10, "NoBalls":10}
BotActions = {"ObstacleBumper":ObstacleBumper, "ObstacleDistance":ObstacleDistance, "PlateuFace":PlateuFace, "PlateuPick":PlateuPick, "PlateuLED":PlateuLED, "ColorWheelCorrect":ColorWheelCorrect, "FlashGateCorrect":FlashGateCorrect, "PedestalLEDCorrect":PedestalLEDCorrect, "PedestalLEDIncorrect":PedestalLEDIncorrect, "PedestalCubeCorrect":PedestalCubeCorrect, "PedestalCubeIncorrect":PedestalCubeIncorrect, "CorralCWCorrect":CorralCWCorrect, "CorralCWIncorrect":CorralCWIncorrect, "BotHung":BotHung, "NoBalls":NoBalls}
ScoreDisplay = Label(window, text = f"{Score.get()}")
ScoreDisplay.grid(column = 0, row = 20, padx = 1, pady = 1)
def ScoreUpdate():
global Score
# potentially unnecessary variable
globalscore = Score.get()
comparescore = 0
comparelist = []
# following for loop checks to see which actions are confirmed to have happened, and stores their names in comparelist
for name, action in BotActions.items():
if action == 1:
comparelist.append(name)
else:
pass
# following for loop checks if a given key from ScoreValues matches an entry in comparelist, and then adds the value of that key to comparescore. If globalscore is less than comparescore, the main score variable (known as Score) is modified to equal comparescore.
for key, value in ScoreValues.items():
if key in comparelist:
comparescore = value
else:
pass
if globalscore < comparescore:
Score.set(comparescore)
ScoreDisplay.config(text = f"{Score.get()}")
else:
pass
def ObstacleConfirmed():
ObstacleComBumper = Checkbutton(window, variable = ObstacleBumper, onvalue = 1, offvalue = 0, command = ScoreUpdate)
ObCoBu = Label(window, text = "The bot completed the course using its bumper switches.")
ObstacleComBumper.grid(column = 1, row = 1, padx = 1, pady = 1)
ObCoBu.grid(column = 2, row = 1, padx = 1, pady = 1)
ObstacleCourseConfirm = Checkbutton(window, width = 1, height = 1, command = ObstacleConfirmed)
ObCoCo = Label(window, text = "The course was completed correctly.")
ObstacleCourseConfirm.grid(column = 0, row = 0, padx = 1, pady = 1)
ObCoCo.grid(column = 1, row = 0, padx = 1, pady = 1)
window.mainloop()
CodePudding user response:
In a nutshell, instead of using:
ScoreDisplay = Label(window, text=f"{Score.get()}")
use:
ScoreDisplay = Label(window, textvariable=Score)
And remove the:
ScoreDisplay.config(text = f"{Score.get()}")
line further down because the update will now happen automatically whenever the value of Score
is changed (usually by calling Score.set()
).
Here's some documentation on the Label
widget that explains the textvariable=
option it has. There's some more on the topic of using tkinter Variables like that in Control variables: the values behind the widgets section of the same document.
Below is your code with the above changes in it along with some I made for testing purposes for testing, plus many code formatting changes I also made to make it more readable by following the PEP 8 - Style Guide for Python Code — something I strongly suggest you begin doing yourself. Anyhow, significant non-cosmetic changes are indicated via # ALL CAP COMMENTS
.
import tkinter as tk
from tkinter.constants import *
window = tk.Tk()
window.geometry('600x600')
window.title("Vex Scoring")
Score = tk.IntVar()
ObstacleBumper = tk.IntVar()
ObstacleDistance = tk.IntVar()
PlateuFace = tk.IntVar()
PlateuPick = tk.IntVar()
PlateuLED = tk.IntVar()
ColorWheelCorrect = tk.IntVar()
FlashGateCorrect = tk.IntVar()
PedestalLEDCorrect = tk.IntVar()
PedestalLEDIncorrect = tk.IntVar()
PedestalCubeCorrect = tk.IntVar()
PedestalCubeIncorrect = tk.IntVar()
CorralCWCorrect = tk.IntVar()
CorralCWIncorrect = tk.IntVar()
BotHung = tk.IntVar()
NoBalls = tk.IntVar()
ScoreValues = {"ObstacleBumper": 10, "ObstacleDistance": 15, "PlateuFace": 5,
"PlateuPick": 5, "PlateuLED": 5, "ColorWheelCorrect": 10,
"FlashGateCorrect": 10, "PedestalLEDCorrect": 15,
"PedestalLEDIncorrect": 10, "PedestalCubeCorrect": 10,
"PedestalCubeIncorrect": 5, "CorralCWCorrect": 5, "CorralCWIncorrect": 2,
"BotHung": 10, "NoBalls": 10}
BotActions = {"ObstacleBumper": ObstacleBumper, "ObstacleDistance": ObstacleDistance,
"PlateuFace": PlateuFace, "PlateuPick": PlateuPick, "PlateuLED": PlateuLED,
"ColorWheelCorrect": ColorWheelCorrect,
"FlashGateCorrect": FlashGateCorrect,
"PedestalLEDCorrect": PedestalLEDCorrect,
"PedestalLEDIncorrect": PedestalLEDIncorrect,
"PedestalCubeCorrect": PedestalCubeCorrect,
"PedestalCubeIncorrect": PedestalCubeIncorrect,
"CorralCWCorrect": CorralCWCorrect, "CorralCWIncorrect": CorralCWIncorrect,
"BotHung": BotHung, "NoBalls": NoBalls}
#ScoreDisplay = tk.Label(window, text=f"{Score.get()}")
ScoreDisplay = tk.Label(window, textvariable=Score)
ScoreDisplay.grid(column=0, row=20, padx=1, pady=1)
def ScoreUpdate():
# global Score # NOT NEEDED
# FOR TESTING PURPOSES, INCREMENT Score EVERY TIME THIS FUNCTION IS CALLED
# SO ScoreDisplay LABEL WILL UPDATE.
Score.set(Score.get() 1)
# # potentially unnecessary variable
# globalscore = Score.get() # YOU'RE RIGHT, IT'S NOT NECESSARY
comparescore = 0
comparelist = []
# following for loop checks to see which actions are confirmed to have
# happened, and stores their names in comparelist.
for name, action in BotActions.items():
if action == 1:
comparelist.append(name)
else:
pass
# following for loop checks if a given key from ScoreValues matches an entry
# in comparelist, and then adds the value of that key to comparescore. If
# globalscore is less than comparescore, the main score variable (known as
# Score) is modified to equal comparescore.
for key, value in ScoreValues.items():
if key in comparelist:
comparescore = value
else:
pass
if Score.get() < comparescore:
Score.set(comparescore) # UPDATES ScoreDisplay LABEL AUTOMATICALLY.
# ScoreDisplay.config(text = f"{Score.get()}") # NO LONGER NECESSARY.
else:
pass
def ObstacleConfirmed():
ObstacleComBumper = tk.Checkbutton(window, variable=ObstacleBumper, onvalue=1,
offvalue=0, command=ScoreUpdate)
ObCoBu = tk.Label(window,
text="The bot completed the course using its bumper switches.")
ObstacleComBumper.grid(column=1, row=1, padx=1, pady=1)
ObCoBu.grid(column=2, row=1, padx=1, pady=1)
ObstacleCourseConfirm = tk.Checkbutton(window, width=1, height=1,
command=ObstacleConfirmed)
ObCoCo = tk.Label(window, text="The course was completed correctly.")
ObstacleCourseConfirm.grid(column=0, row=0, padx=1, pady=1)
ObCoCo.grid(column=1, row=0, padx=1, pady=1)
window.mainloop()
CodePudding user response:
action == 1
inside ScoreUpdate()
should be action.get() == 1
because action
is an IntVar
.
def ScoreUpdate():
...
for name, action in BotActions.items():
if action.get() == 1: ### used action.get() instead of action
comparelist.append(name)
else:
pass
...