Tkinter tutorial Part 1 – Making a Tkinter Canvas

Tkinter Canvas

Hello everyone! Let’s learn how to create a Tkinter Canvas in this tutorial. Since the Tkinter library is really large, we’ll be covering a lot of interesting topics in the coming time!


What is Tkinter?

Tkinter is a Python interface using which we can create GUIs (Graphical User Interfaces).

This library is cross-platform, which means it is an ideal choice for Python developers since your application code can now be platform-independent!

The best part about this is that it already comes in pre-installed with Python! So there’s no need to install this separately.

But just in case, we’ll check if Tkinter is working properly on our system. So go to your Windows Command Prompt (or Bash on Linux/Mac) and type:

python -m tkinter

A sample window should appear like this, indicating that Tkinter is working:

And if you want to use this library, it’s just one line!

import tkinter

Now, we can get started on writing our first program on Tkinter. For this, I will be building a simple program that displays images on the screen.

Let’s get started on our first step to building the application: Creating a new Canvas!


Creating a Tkinter Canvas

Step 1: Create the application and the master object handle

Before we can create our canvas, we need to instantiate the Python Tkinter object. The default constructor will instantiate a Tkinter object.

This object is usually called the root object (master object). This is because your GUI application uses all calls through this object. Your application cannot run without this object.

To create a master object, do the following:

import tkinter as tk

# Create our master object to the Application
master = tk.Tk()

We have now created the master object. Now, to run the application, typically, such programs are designed as an event loop.

Now, we also need a handle to our Application, so that the application can use this object and pass it to the event loop.

The class tk.Frame has this for us. So we’ll create an Application class which inherits this class. So now we can directly call the main loop from our application object.

class Application(tk.Frame):
	def __init__(self, master=None):
		# We need the master object to
		# initialize important stuff
		super().__init__(master) # Call tk.Frame.__init__(master)
		self.master = master # Update the master object after tk.Frame() makes necessary changes to it

We create an application class called Application. The constructor for this class calls the base class (tk.Frame) constructor and passes the master object, so that important stuff can be initialized.

Now, super.__init__(master) will actually modify the master object, so we’ll update our own copy to the most recent one since we’ll need it for other calls.

The main program of your application object app runs under the main event loop called app.mainloop(). This is what actually does all the calls from Python to lower level languages on your machine.

To start the main loop, simply call this function!

import tkinter as tk

class Application(tk.Frame):
	def __init__(self, master=None):
		# We need the master object to
		# initialize important stuff
		super().__init__(master) # Call tk.Frame.__init__(master)
		self.master = master # Update the master object after tk.Frame() makes necessary changes to it

# Create our master object to the Application
master = tk.Tk()
# Create our application object
app = Application(master=master)
# Start the mainloop
app.mainloop()

Now, if you run this program, you’ll get the following output.

Sample Tkinter Output
Sample Tkinter Output

Part 2: Create our Tkinter Canvas

Now, we’re ready to create our Canvas!

We can use the tk.Canvas() method to create the canvas for us.

It’s initialization is as follows:

canvas = tk.Canvas(master_object, bg="blue", width=canvas_width, height=canvas_height)

This line will create a canvas object with a background of blue, and the specified width and height (pixels).

But here, we still cannot directly start the loop. We need to apply the changes in the canvas and pack the objects onto it. This needs canvas.pack().

Now, we can display our empty canvas in our main loop!

import tkinter as tk

class Application(tk.Frame):
	def __init__(self, master=None):
		# We need the master object to
		# initialize important stuff
		super().__init__(master) # Call tk.Frame.__init__(master)
		self.master = master # Update the master object after tk.Frame() makes necessary changes to it
	def createCanvas(self, canvas_width, canvas_height):
		# Create our canvas (blue background)
		canvas = tk.Canvas(self.master, bg="blue", width=canvas_width, height=canvas_height)
		return canvas

# Create our master object to the Application
master = tk.Tk()
# Create our application object
app = Application(master=master)
canvas = app.createCanvas(300, 300)
# Pack items into the canvas
canvas.pack()
# Start the mainloop
app.mainloop()

Now let’s run this program:

Canvas Blue
Canvas Blue

Great! This seems to work as expected. Now let’s do some more stuff on the canvas.

Let’s display this image of Debian Linux on our Application.

Debian
Debian

We can create an image item using the tk.PhotoImage class.

img = tk.PhotoImage(file="debian.png") # Create our PhotoImage object
image = canvas.create_image(100, 100, anchor=NW, image=img) # Create the image on our canvas

Let’s put it under a addImage() method for our class.

        def addImage(self, canvas, filename, image_x, image_y, direction=tk.NW):
		self.img = tk.PhotoImage(file=filename) # Create our PhotoImage object
		canvas.create_image(image_x, image_y, anchor=direction, image=self.img) # Create the image on our canvas
		return canvas

Now, the whole program looks like this:

import tkinter as tk

class Application(tk.Frame):
	def __init__(self, master=None):
		# We need the master object to
		# initialize important stuff
		super().__init__(master) # Call tk.Frame.__init__(master)
		self.master = master # Update the master object after tk.Frame() makes necessary changes to it
	def createCanvas(self, canvas_width, canvas_height):
		# Create our canvas (blue background)
		canvas = tk.Canvas(self.master, bg="blue", width=canvas_width, height=canvas_height)
		return canvas
	def addImage(self, canvas, filename, image_x, image_y, direction=tk.NW):
		img = tk.PhotoImage(file=filename) # Create our PhotoImage object
		canvas.create_image(image_x, image_y, anchor=direction, image=img) # Create the image on our canvas
		return canvas

# Create our master object to the Application
master = tk.Tk()
# Create our application object
app = Application(master=master)
canvas = app.createCanvas(300, 300)
canvas = app.addImage(canvas, "debian.png", 50, 50)
# Pack items into the canvas
canvas.pack()
# Start the mainloop
app.mainloop()

But when you run the program, you’ll get just the blue canvas again. Why is this happening?

According to this thread on Stack Overflow, the image object img is being garbage collected by Python and is not displayed.

Why? Apparently the tk.PhotoImage object has this property. So, we need an extra reference in our class, to make sure Python doesn’t immediately discard it. So, we can just replace img with self.img on our addImage() method, and this solves the problem!

import tkinter as tk


class Application(tk.Frame):
	def __init__(self, master=None):
		# We need the master object to
		# initialize important stuff
		super().__init__(master) # Call tk.Frame.__init__(master)
		self.master = master # Update the master object after tk.Frame() makes necessary changes to it
	def createCanvas(self, canvas_width, canvas_height):
		# Create our canvas (blue background)
		canvas = tk.Canvas(self.master, bg="blue", width=canvas_width, height=canvas_height)
		return canvas
	def addImage(self, canvas, filename, image_x, image_y, direction=tk.NW):
		self.img = tk.PhotoImage(file=filename) # Create our PhotoImage object
		canvas.create_image(image_x, image_y, anchor=direction, image=self.img) # Create the image on our canvas
		return canvas

# Create our master object to the Application
master = tk.Tk()
# Create our application object
app = Application(master=master)
canvas = app.createCanvas(300, 300)
canvas = app.addImage(canvas, "debian.png", 50, 50)
# Pack items into the canvas
canvas.pack()
# Start the mainloop
app.mainloop()

If you now run this program, you’ll get the correct output:

Canvas Image
Canvas Image

We’ve solved this problem!

Now, you can continue doing various stuff with Tkinter, such as drawing shapes and displaying similar images. The documentation may help you along.


Conclusion

In this article, we learned about Tkinter Canvas, and how we can create a Tkinter canvas and display it on our screen. Stay tuned for more tutorials on this module!

References