Trong phần này chúng ta sẽ học cách vẽ các đối tượng hình học trong Tkinter bằng cách sử dụng widget Canvas.
Vẽ đoạn thẳng
Để vẽ đoạn thẳng thì chúng ta dùng phương thức create_line()
của lớp Canvas
. Bạn cứ hiểu
Canvas
giống như một tờ giấy để chúng ta vẽ mọi thứ trên đó, nếu bạn đã từng lập trình HTML5 thì chắc không còn xa lạ gì với canvas.
from tkinter import Tk, Canvas, Frame, BOTH class Example(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.initUI() def initUI(self): self.parent.title("Lines") self.pack(fill=BOTH, expand=1) canvas = Canvas(self) canvas.create_line(15, 25, 200, 25) canvas.create_line(300, 25, 300, 200, dash=(4, 2)) canvas.create_line(55, 85, 155, 85, 105, 180, 55, 85) canvas.pack(fill=BOTH, expand=1) root = Tk() ex = Example(root) root.geometry("400x250+300+300") root.mainloop()
Trong ví dụ trên chúng ta vẽ một vài đoạn thẳng lên canvas.
canvas = Canvas(self)
Đầu tiên chúng ta tạo đối tượng Canvas
với tham số self
để canvas bao phủ toàn bộ cửa sổ.
canvas.create_line(15, 25, 200, 25)
Phương thức create_line()
nhận vào tham số là tọa độ x, y của điểm bắt đầu và điểm kết thúc của một đoạn thẳng.
canvas.create_line(300, 35, 300, 200, dash=(4, 2))
Tham số dash
tùy chỉnh kiểu vẽ là các đường nét đứt, ở ví dụ trên, dash=(4, 2)
nghĩa là vẽ các nốt dài 4 pixel cách nhau 2 pixel.
canvas.create_line(55, 85, 155, 85, 105, 180, 55, 85)
Bạn cũng có thể đưa vào nhiều điểm, dòng code trên đưa vào 3 điểm để vẽ một hình tam giác.
Vẽ màu
Màu trong máy tính là màu RGB, là tổ hợp của 3 giá trị đỏ (Red), xanh lá (Green) và xanh lam (Blue).
from tkinter import Tk, Canvas, Frame, BOTH class Example(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.initUI() def initUI(self): self.parent.title("Colors") self.pack(fill=BOTH, expand=1) canvas = Canvas(self) canvas.create_rectangle(30, 10, 120, 80, outline="#fb0", fill="#fb0") canvas.create_rectangle(150, 10, 240, 80, outline="#f50", fill="#f50") canvas.create_rectangle(270, 10, 370, 80, outline="#05f", fill="#05f") canvas.pack(fill=BOTH, expand=1) root = Tk() ex = Example(root) root.geometry("400x100+300+300") root.mainloop()
Trong ví dụ trên chúng ta vẽ 3 hình chữ nhật với 3 màu khác nhau.
canvas.create_rectangle(30, 10, 120, 80, outline="#fb0", fill="#fb0")
Phương thức create_rectangle()
tạo một hình chữ nhật trên canvas với 4 tham số đầu tiên là tọa độ x, y của điểm trái-trên và điểm phải-dưới. Tham số outline
là giá trị màu đường viền, tham số fill
là giá trị màu của hình chữ nhật, tất cả đều ở dạng hexa.
Vẽ một số đối tượng hình học khác
from tkinter import Tk, Canvas, Frame, BOTH class Example(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.initUI() def initUI(self): self.parent.title("Shapes") self.pack(fill=BOTH, expand=1) canvas = Canvas(self) canvas.create_oval(10, 10, 80, 80, outline="gray", fill="gray", width=2) canvas.create_oval(110, 10, 210, 80, outline="gray", fill="gray", width=2) canvas.create_rectangle(230, 10, 290, 60, outline="gray", fill="gray", width=2) canvas.create_arc(30, 200, 90, 100, start=0, extent=210, outline="gray", fill="gray", width=2) points = [150, 100, 200, 120, 240, 180, 210, 200, 150, 150, 100, 200] canvas.create_polygon(points, outline="gray", fill="gray", width=2) canvas.pack(fill=BOTH, expand=1) root = Tk() ex = Example(root) root.geometry("330x220+300+300") root.mainloop()
Trong ví dụ trên chúng ta vẽ 5 hình là hình tròn, hình elip, hình chữ nhật, hình quạt và một đa giác.
canvas.create_oval(10, 10, 80, 80, outline="red", fill="green", width=2)
Phương thức create_oval()
dùng để vẽ hình tròn. Bốn tham số đầu tiên là tọa độ x, y của điểm trái-trên và phải-dưới của hình tròn (bởi vì hình tròn trong Tkinter được nằm trong một hình chữ nhật).
canvas.create_arc(30, 200, 90, 100, start=0, extent=210, outline="#f11", fill="#1f1", width=2)
Phương thức create_arc()
vẽ hình quạt, 4 tham số đầu tiên cũng là tọa độ hình chữ nhật chứa hình quạt này. Tham số start
là hướng mà quạt hướng tới, tham số extend
là độ lớn của quạt, cả 2 tham số này đều có đơn vị độ (từ 0 đến 360 độ).
points = [150, 100, 200, 120, 240, 180, 210, 200, 150, 150, 100, 200] canvas.create_polygon(points, outline='red', fill='green', width=2)
Phương thức create_polygon()
vẽ một đa giác, tham số là tọa độ x, y của các điểm, bạn có thể đưa các điểm này vào bằng tay như các phương thức khác hoặc lưu các điểm trong một list rồi đưa list này vào.
Hiển thị ảnh từ file
from tkinter import Tk, Canvas, Frame, BOTH, NW from PIL import Image, ImageTk class Example(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.initUI() def initUI(self): self.parent.title("Image") self.pack(fill=BOTH, expand=1) self.img = Image.open("C:\\tatras.jpeg") self.tatras = ImageTk.PhotoImage(self.img) canvas = Canvas(self, width=self.img.size[0]+20, height=self.img.size[1]+20) canvas.create_image(10, 10, anchor=NW, image=self.tatras) canvas.pack(fill=BOTH, expand=1) root = Tk() ex = Example(root) root.mainloop()
Ví dụ trên vẽ hình từ file lên canvas.
self.img = Image.open("tatras.jpg") self.tatras = ImageTk.PhotoImage(self.img)
Ở đây chúng ta dùng lớp Image
và ImageTk
từ module PIL
. Module này không có sẵn trong Python mà bạn phải tự cài thêm vào.
canvas = Canvas(self, width=self.img.size[0]+20, height=self.img.size[1]+20)
Chúng ta tạo đối tượng canvas
với chiều dài và chiều rộng của file cộng thêm 20 pixel.
canvas.create_image(10, 10, anchor=NW, image=self.tatras)
Để hiện hình từ file lên canvas chúng ta dùng phương thức create_image().
Hai tham số đầu tiên là tọa độ góc trái-trên của hình. Tham số anchor=NW
có tác dụng cắt hình từ vị trí NW = North West = tây-bắc)
cho đến hết góc phải-dưới của ảnh, tức là lấy nguyên toàn bộ ảnh, mặc định nếu không đặt tham số này thì chương trình chỉ hiển thị phần giữa (CENTER) của ảnh. Bạn có thể thử các giá trị khác như N, E, SE (nhớ import các hằng số vô trước)… dưới đây là sơ đồ của các hướng.
Tham số image
là đối tượng ảnh cần hiển thị.
Ghi chữ lên canvas
from tkinter import Tk, Canvas, Frame, BOTH, W class Example(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.initUI() def initUI(self): self.parent.title("Lyrics") self.pack(fill=BOTH, expand=1) canvas = Canvas(self) canvas.create_text(20, 30, anchor=W, font="VNI-Dom 18", text="Most relationships seem so transitory") canvas.create_text(20, 60, anchor=W, font="VNI-Dom 18", text="They're good but not the permanent one") canvas.create_text(20, 130, anchor=W, font="VNI-Dom 18", text="Who doesn't long for someone to hold") canvas.create_text(20, 160, anchor=W, font="VNI-Dom 18", text="Who knows how to love without being told") canvas.create_text(20, 190, anchor=W, font="VNI-Dom 18", text="Somebody tell me why I'm on my own") canvas.create_text(20, 220, anchor=W, font="VNI-Dom 18", text="If there's a soulmate for everyone") canvas.pack(fill=BOTH, expand=1) root = Tk() ex = Example(root) root.geometry("420x250+300+300") root.mainloop()
Đoạn code trên thực hiện “vẽ” lời bài hát lên canvas.
canvas.create_text(20, 30, anchor=W, font="VNI-Dom 18", text="Most relationships seem so transitory")
Chúng ta dùng phương thức create_text()
để hiển thị chữ lên canvas. Hai tham số đầu là tọa độ x, y của góc trái trên. Tham số font="VNI-Dom 18"
tức là dùng font VNI-Dom với độ lớn là 18px. Tham số text là nội dung đoạn text được in lên canvas.