Search code examples
pythonpython-3.xtkinter

First global variable not being found in function, causing error. Second global variable does not cause an error?


Attempting to make an updateable scoreboard companion program for a game with friends. Very new to programing so for learning/first-steps/troubleshooting, set a button that contains the players name, a label that shows their point total, and a checkbox that can be selected depending on the desired point increase. Once the desired point increase is selected, the player's button can be pressed, and the score should be updated. Once the code works, I can expand on the number of player buttons, scores shown and checkboxes. Issue I have encountered is the variable (score1) seems to be an "unresolved reference" (error shown in PyCharm) by the function I have made (score_sum), while another variable (score_update) does not cause an error.

from tkinter import *
root = Tk()

score1 = IntVar()

score_update = IntVar()


def score_sum():
    if score_update == 1:
        newscore = score1 + 1
        score1 = newscore
    else:
        print("No points scored.")


playername = Button(root, text="Player Name", command=score_sum)
playername.pack()

playerscore = Label(root, textvariable=score1)
playerscore.pack()

plusone = Checkbutton(root, text="1 point", variable=score_update, onvalue=1, offvalue=0)
plusone.pack()

root.mainloop()

Started writing this line-by-line, knowing what I wanted the final code to look like before troubleshooting. Once the error was encountered deleted the line hoping that it would clear the error. Since I had left PyCharm open overnight, tried closing and reopening in desperate hopes the error would clear. Not sure what to change since one variable works while another does not.


Solution

  • The problem isn't related to global variables, but rather with how you're handling the two IntVars. When you do this:

    score1 = IntVar()
    

    you're creating an instance of a tkinter IntVar object and storing that in the variable you've called score1. Because of that, when you then do something like

    score1 = newscore
    

    you're replacing that IntVar object with whatever newscore happens to be.

    Instead, you need to use their dedicated get and set methods like so:

    from tkinter import *
    root = Tk()
    
    score1 = IntVar()
    score_update = IntVar()
    
    
    def score_sum():
        # use 'get' to query the existing value(s)
        if score_update.get() == 1:
            newscore = score1.get() + 1
            # use 'set' to update the IntVar with a new value
            score1.set(newscore)
        else:
            print("No points scored.")
    
    
    playername = Button(root, text="Player Name", command=score_sum)
    playername.pack()
    
    playerscore = Label(root, textvariable=score1)
    playerscore.pack()
    
    plusone = Checkbutton(root, text="1 point", variable=score_update, onvalue=1, offvalue=0)
    plusone.pack()
    
    root.mainloop()
    

    Using get and set like this allows you to read/write the value that's stored within those IntVar instances, and in turn allows your other tkinter widgets to interact with those values appropriately.

    And for what it's worth, the other tkinter variable classes, StringVar, BooleanVar, etc., all behave similarly