Canvas¶
The Canvas widget can be used to draw lines, shapes, and text to create complex drawings and graphs. The origin (0, 0) of the canvas is in the top left corner. It has the keyword options:
- background = background color
- borderwidth
- height
- width
Draw lines and rectangles¶
To draw lines and rectangles, use these create methods:
- create_line()
- create_rectangle()
from tklib import *
app = App('Canvas with lines and rectangles')
c = Canvas(width=600, height=300, background='lightblue')
c.create_line(10, 10, 200, 200, fill='red')
c.create_line(20, 10, 210, 200, fill='blue', width=3)
c.create_rectangle(100, 200, 150, 250, fill='green', width=2)
c.create_rectangle(300, 100, 580, 250, fill='yellow', width=5)
app.run()
Create text¶
Text can be added to a canvas with this function:
- create_text()
from tklib import *
app = App('Canvas with ovals and text')
c = Canvas(width=600, height=300, background='lightblue')
c.create_line(10, 10, 200, 200, fill='red')
c.create_line(20, 10, 210, 200, fill='blue', width=3)
c.create_oval(100, 200, 150, 250, fill='green', width=2)
c.create_oval(300, 100, 580, 250, fill='yellow', width=5)
c.create_text(300, 150, text="Python", font='Arial 48')
c.create_text(300, 250, text="Canvas", font='Zapfino 72')
app.run()
Paint with ovals¶
Small ovals can be used to paint with the mouse, by binding a callback function to the mouse movement.
"""Painting with ovals."""
from tklib import *
class Demo(App):
def __init__(self):
super().__init__()
Label("Painting using ovals", font="Arial 24")
self.c = Canvas(width=600, height=300, background='lightblue')
self.c.bind('<B1-Motion>', self.paint)
def paint(self, event):
"""Draw ovals on the canvas."""
x0, y0 = event.x-1, event.y-1
x1, y1 = event.x+1, event.y+1
self.c.create_oval(x0, y0, x1, y1, fill='blue')
Demo().run()
Polygons¶
We can add our own methods to the Canvas class. For example we can define a method to add a polygon.
def polygon(self, x0, y0, r, n, **kwargs):
points = []
for i in range(n):
a = 2 * math.pi * i / n
x = x0 + math.sin(a) * r
y = y0 + math.cos(a) * r
points.append(x)
points.append(y)
self.create_polygon(points, **kwargs)
from tklib import *
app = App('Draw a polygon')
c = Canvas(width=600, height=300, background='lightblue')
c.polygon(150, 150, 100, 6, fill='blue')
c.polygon(450, 150, 80, 8, fill='red', width=5)
app.run()
Random circles¶
The following program places circles of random size at random locations.
from tklib import *
app = App('Random circles')
w, h = 600, 300
c = Canvas(width=w, height=h, background='lightblue')
for i in range(50):
x = random.randint(0, w)
y = random.randint(0, h)
r = random.randint(10, 100)
c.create_oval(x, y, x+r, y+r)
app.run()
Canvas configuration¶
"""Canvas config."""
from tklib import *
class Demo(App):
def __init__(self):
super().__init__()
Label("Canvas configuration", font="Arial 24")
Spinbox('width', 'App.c["width"]=self.var.get()', inc=50, to=1000)
Spinbox('height', 'App.c["height"]=self.var.get()', inc=50, to=1000)
Combobox('background', 'white;yellow;pink;light blue', 'App.c.config(background=self.var.get())')
Combobox('highlightcolor', 'black;red;blue;green', 'App.c.config(highlightcolor=self.var.get())')
Combobox('relief', 'flat;sunken;raised;groove', 'App.c.config(relief=self.var.get())')
Combobox('state', 'normal;disabled;hidden', 'App.c.config(state=self.var.get())')
Spinbox('borderwidth', 'App.c.config(borderwidth=self.var.get())')
Button('Config', 'print(App.c.config())')
App.c = Canvas()
Demo().run()
Canvas configuration with tree view¶
"""Canvas configuration with Treeview"""
from tklib import *
class Option:
def __init__(self, widget):
self.w = widget
tree = Treeview(columns=(0))
tree.column(0, width=150)
tree.heading(0, text='Value')
tree.grid(row=0, column=2)
d = self.w.config()
print(d)
for (k, v) in d.items():
if len(v)>2:
tree.insert('', 'end', text=k, values=v[-1])
class Demo(App):
def __init__(self):
super().__init__()
Label("Canvas configuration", font="Arial 24")
App.stack[-1]=Frame()
App.c = Canvas(background='lightblue',
borderwidth=10,
height=250)
d = App.c.config()
tree = Treeview(columns=(0))
tree.column(0, width=150)
tree.heading(0, text='Value')
tree.grid(row=0, column=1)
for (k, v) in d.items():
if len(v)>2:
tree.insert('', 'end', text=k, values=v[-1])
Option(App.c)
Demo().run()
Draw shapes with the mouse¶
"""Draw shapes with the mouse."""
from tklib import *
class Demo(App):
def __init__(self):
super().__init__()
Label("Drawing shapes", font="Arial 24")
Spinbox('width', 'App.c["width"]=self.val.get()', inc=50, to=1000)
Spinbox('height', 'App.c["height"]=self.val.get()', inc=50, to=1000)
Separator()
Combobox('fill', 'black;red;green;blue;orange;cyan',
'App.c.itemconfig(App.c.id, fill=self.val.get())')
Spinbox('width', 'App.c.itemconfig(App.c.id, width=self.val.get())', from_=1, to=20)
Button('Delete', 'App.c.delete(App.c.id)')
Button('Delete All', 'App.c.delete("all")')
Combobox('type', 'arc;line;rectangle;oval',
'App.c.itemconfig(App.c.id, fill=self.val.get())')
Button('Config', 'print(App.c.itemconfig(1))')
App.c = Canvas()
print(vars(App.c))
print()
print(dir(App.c))
App.c.create_rectangle(20, 20, 150, 100)
Demo().run()
Draw straight lines with the mouse¶
In order to draw with the mouse we have to add two bindings to the canvas:
- <Button-1> to initiate the drawing, calling the
start()
method - <B1_Motion> to update the current drawing, calling the
move()
method
# draw straight lines on a canvas
from tklib import *
class Canvas(tk.Canvas):
"""Define a canvas with line drawing"""
def __init__(self, **kwargs):
# super(Canvas, self).__init__(App.stack[-1], width=w, height=h, bg='light blue')
super(Canvas, self).__init__(App.stack[-1], **kwargs)
self.grid()
self.bind('<Button-1>', self.start)
self.bind('<B1-Motion>', self.move)
self.bind('<D>', self.print_msg)
self.bind('<Key>', self.print_msg)
self.bind('<Return>', self.print_msg)
def start(self, event=None):
# Execute a callback function.
self.x0 = event.x
self.y0 = event.y
self.id = self.create_line(self.x0, self.y0, self.x0, self.y0)
self.itemconfig(self.id, fill=color.var.get())
self.itemconfig(self.id, width=thickness.var.get())
def move(self, event=None):
self.x1 = event.x
self.y1 = event.y
self.coords(self.id, self.x0, self.y0, self.x1, self.y1)
def print_msg(self, event):
print(event)
app = App('Drawing lines on a canvas')
color = Combobox('Color', 'black;red;green;blue;yellow;cyan;magenta')
thickness = Combobox('Thickness', '1;2;5;10;20')
Canvas(width=600, height=200)
app.run()