Pat6089
Pat6089

Reputation: 13

Tkinter - Python 3 - Adding an Increment Counter into a class window?

class AppetiserClass():
    root = Tk()
    root.title("Appetiser Page")
    root.geometry("1920x1080")


    meal1 = 0

    def plus1():
        global meal1
        meal1 = meal1 + 1
        DisplayButton["text"]=str(meal1)
        return

    def neg1():
        global meal1
        meal1 = meal1 + 1
        DisplayButton["text"]=str(meal1)
        return

    app = Frame(root)
    app.grid()

    Label(app, text = "", width = 75, height = 20).grid(row = 1, column = 0, sticky = N)

    DisplayButton = Button(app, text = meal1)
    DisplayButton.grid(column = 1, row = 2, sticky = W)
    DisplayButton.config(height = 10, width = 10 )

    Plus1Button = Button(app, text = "+1", command=plus1, bg="green")
    Plus1Button.grid(column = 2, row = 2, sticky = W)
    Plus1Button.config(height = 10, width = 10 )

    Neg1Button = Button(app, text = "-1", command=neg1, bg="green")
    Neg1Button.grid(column = 3, row = 2, sticky = W)
    Neg1Button.config(height = 10, width = 10 )

    root.mainloop()

The problem I am having is that I have set a value to my global variable (meal1, being 0) but when I press the +1, or -1 button, a value is not being displayed on the "DislpayButton" and I am receiving this message: "NameError: global name 'DisplayButton' is not defined "

"DisplayButton", is a button i have placed, to display a value onto. Nothing more, but I am receiving this error message.

If i remove the classes, and just run this code, with the single window, The code works fine.

Any help would be much appreciated!

Upvotes: 0

Views: 2787

Answers (1)

furkle
furkle

Reputation: 5059

If your indentation is correct, the problem isn't that DisplayButton and meal1 are global, it's that they're class-level and you're not accessing it that way, which means you should use self keyword to access it. (It doesn't have to be "self" - the first argument of any function in a class always defines the variable through which you can access other members in the same class - but it's Python style to use "self.") Add self as an argument to all your functions in that class, like so:

def neg1(self):

And then access meal1 and DisplayButton through self:

 self.meal1 += 1

and:

 self.DisplayButton["text"] = str(meal1)

I've re-written your class so that all the important stuff within the class can be accessed by everything else using self:

from tkinter import *

class AppetiserClass:
    meal1 = 0
    root = Tk()
    app = Frame(self.root)

    def __init__(self):
        self.root.title("Appetiser Page")
        self.root.geometry("1920x1080")

        self.app.grid()

        Label(self.app, text = "", width = 75, height = 20).grid(row = 1, column = 0, sticky = N)

        self.DisplayButton = Button(self.app, text = self.meal1)
        self.DisplayButton.grid(column = 1, row = 2, sticky = W)
        self.DisplayButton.config(height = 10, width = 10 )

        self.Plus1Button = Button(self.app, text = "+1", command=self.plus1, bg="green")
        self.Plus1Button.grid(column = 2, row = 2, sticky = W)
        self.Plus1Button.config(height = 10, width = 10 )

        self.Neg1Button = Button(self.app, text = "-1", command=self.neg1, bg="green")
        self.Neg1Button.grid(column = 3, row = 2, sticky = W)
        self.Neg1Button.config(height = 10, width = 10 )

        self.root.mainloop()

    def plus1(self):
        self.meal1 += 1
        self.DisplayButton["text"]=str(self.meal1)

    def neg1(self):
        self.meal1 -= 1
        self.DisplayButton["text"]=str(self.meal1)

if __name__ == "__main__":
    AppetiserClass()

I changed a decent amount. First off, you had a lot of code written outside any particular method, which is something I prefer to keep inside the class methods except for class variable definitions (meal1 = 0 and etc.). It's fairly arbitrary - anything defined within a method as self.whatever has the same accessibility as stuff defined at the class scope. I've also made it so that you can keep reference to your buttons with self.ButtonName. Lastly, I've made it so that the window is instantiated only if you're running the file and not importing your code into a different file.

Upvotes: 1

Related Questions