I'm not going to describe the ins and outs of classes and object-oriented programming - Google it. I will say that a class is the definition of how an object works and an object is what a program creates from the class. Objects run in code, classes are the definition of objects. The class can define data which can be used throughout the object. The class can also define functions to work within the object, using the object's data.
Data variables defined in a class are known as fields and when they are used outside of the object they can be known as properties. Functions defined in a class that get used from outside the object the class defines are known as methods.
If we define a class in which we include all of the data fields we need to make our game of Rye work and define the event handlers there too, the event handlers can access any of the data they need. The global variable disappear with a touch of class.
Python has good support for classes. If you want to know more, take a look at the documentation.
I have converted the previous program to a version that uses a class, without adding any extra functionality.
from Tkinter import *
class ryeapp(Tk): 1
def __init__(self,parent): 2
# create the shared variables 4
# GUI initialisation
# create the canvas for the game
self.cnvs = Canvas(self, height=300, width=300)
self.cnvs.grid(column=0, row=0, columnspan=4)
# draw Rye at position 2,2
# set the canvas to receive the focus, so keypresses are captured
def ryeDown(self,event): 5
self.cnvs.move(self.ryeId, 0, 20)
self.cnvs.move(self.ryeId, 0, -20)
self.cnvs.move(self.ryeId, -20, 0)
self.cnvs.move(self.ryeId, 20, 0)
if __name__ == "__main__":
app = ryeapp(None) 6
This version is very similar to the last one, except that almost all of the program is now wrapped up in a class call ryeapp 1. The class is based on the Tk class, so our class extends the Tk class. Extending a class is known as inheritance and a fundamental part of object-oriented programming. All of the functions of Tk are now part of our class and we can add as much extra stuff as we want. This is not the only way to use a class, when you know more you might do it another way.
Classes can define a special function that is always called __init__ (that's two underscores before and after the init). Whenever the class is used to create an object this function will be called, so this is a great way to initialise our GUI. We define it on line 2 which is slightly different from the def statements we used before. Firstly it is indented within the class level. This means it is part of the class. Secondly the first parameter is self. This is a special reference to the rest of the class. This is how all the parts of the class can see each other. We'll use self whenever we want to refer to other parts of the class.
We have based our class on Tk. Tk has its own __init__ function, so the first thing we must do is call it, as in line 3. All of the rest of the function is similar to what we did in the previous program and it is worth comparing them. All of the variables we created as global variables before we can now create as fields in the class, starting at line 4.Everywhere we want to refer to a field we must use self. as the prefix to use the one in the class and not some other variable.
The event handlers are now defined as part of the class, starting on line 5. They can refer to the self.cnvs and self.ryeId safely.
Lastly when we have defined the class we need to use it to create the object that actually does something. Line 6 does this, creating the object app from the class ryeapp, passing None as the parent name, since this is the top level window it has no parent. The creation of the object automatically called our __init__ function which here does most of the work. When that is complete the mainloop() can start which waits for the events which get processed as we have seen before.
You can download a copy of classRye.py here.