Canvas

В tkinter от класса Canvas создаются объекты-холсты, на которых можно "рисовать", размещая различные фигуры и объекты. Делается это с помощью вызовов соответствующих методов.

При создании экземпляра Canvas необходимо указать его ширину и высоту. При размещении геометрических примитивов и других объектов указываются их координаты на холсте. Точкой отсчета является верхний левый угол.

Координатная ось

В программе ниже создается холст. На нем с помощью метода create_line() рисуются отрезки. Сначала указываются координаты начала (x1, y1), затем – конца (x2, y2).

from tkinter import *
root = Tk()
 
c = Canvas(root, width=200, height=200, bg='white')
c.pack()
 
c.create_line(10, 10, 190, 50)
 
c.create_line(100, 180, 100, 60, fill='green',
                width=5, arrow=LAST, dash=(10,2),
                activefill='lightgreen',
                arrowshape="10 20 10")
 
root.mainloop()

Метод create_line()

Остальные свойства являются необязательными. Так activefill определяет цвет отрезка при наведении на него курсора мыши.

Создание прямоугольников методом create_rectangle():

… 
c.create_rectangle(10, 10, 190, 60)
 
c.create_rectangle(60, 80, 140, 190, fill='yellow', outline='green',
                    width=3, activedash=(5, 4))

Метод create_rectangle()

Первые координаты – верхний левый угол, вторые – правый нижний. В приведенном примере, когда на второй прямоугольник попадает курсор мыши, его рамка становится пунктирной, что определяется свойством activedash.

Методом create_polygon() рисуется произвольный многоугольник путем задания координат каждой его точки:

… 
c.create_polygon(100, 10, 20, 90, 180, 90)
 
c.create_polygon(40, 110, 160, 110, 190, 180, 10, 180,
                fill='orange', outline='black')

Метод create_polygon()

Для удобства координаты точек можно заключать в скобки:

…
c.create_polygon((40, 110), (160, 110), (190, 180), (10, 180),
                fill='orange', outline='black')

Метод create_oval() создает эллипсы. При этом задаются координаты гипотетического прямоугольника, описывающего эллипс. Если нужно получить круг, то соответственно описываемый прямоугольник должен быть квадратом.

…
c.create_oval(50, 10, 150, 110, width=2)
c.create_oval(10, 120, 190, 190, fill='grey70', outline='white')

Метод create_oval()

Более сложные для понимания фигуры получаются при использовании метода create_arc(). В зависимости от значения опции style можно получить сектор (по умолчанию), сегмент (CHORD) или дугу (ARC). Также как в случае create_oval() координаты задают прямоугольник, в который вписана окружность (или эллипс), из которой "вырезают" сектор, сегмент или дугу. Опции start присваивается градус начала фигуры, extent определяет угол поворота.

… 
c.create_oval(10, 10, 190, 190, fill='lightgrey', outline='white')
c.create_arc(10, 10, 190, 190, start=0, extent=45, fill='red')
c.create_arc(10, 10, 190, 190, start=180, extent=25, fill='orange')
c.create_arc(10, 10, 190, 190, start=240, extent=100, style=CHORD, fill='green')
c.create_arc(10, 10, 190, 190, start=160, extent=-70, style=ARC, outline='darkblue', width=5)

Метод create_arc()

В данном примере светло-серый круг используется исключительно для наглядности.

На холсте можно разместить текст. Делается это с помощью метода create_text():

… 
c.create_text(100, 100, text="Hello World,\nPython\nand Tk", 
                justify=CENTER, font="Verdana 14")
c.create_text(200, 200, text="About this", 
                anchor=SE, fill="grey")

Метод create_text()

По умолчанию в заданной координате располагается центр текстовой надписи. Чтобы изменить это и, например, разместить по указанной координате левую границу текста, используется якорь со значением W (от англ. west – запад). Другие значения: N, NE, E, SE, S, SW, W, NW. Если букв, задающих сторону привязки, две, то вторая определяет вертикальную привязку (вверх или вниз «уйдет» текст от заданной координаты). Свойство justify определяет лишь выравнивание текста относительно себя самого.

Практическая работа

Создайте на холсте подобное изображение:

Создание изображения на холсте в Tkinter

Для создания травы используется цикл.

Курс с примерами решений практических работ: android-приложение, pdf-версия.

Комментарии

Практическая работа.
from tkinter import *
root=Tk()
c=Canvas(root, width=200, height=200, bg='white')
c.pack()
c.create_oval(150,10,190,50, fill='orange', outline='white')
c.create_line(100, 175, 100, 50, fill='lightblue',width=100, arrow=LAST,arrowshape="50 50 20")
i=-40
while i<200:
    c.create_arc(i,400,(i+40),170,start=180, extent=-93, styl=ARC, outline='green', width=2)
    i+=10
 
root.mainloop()

from tkinter import *
 
 
root = Tk()
class grass:
    def __init__(self,x,y):
        self.x = x
        self.y = y
        c.create_arc(self.x + i, 165, self.y + i, 235, start=180, extent=-90, style=ARC, outline='green', width=2)
 
c = Canvas(width=200, height=200, bg='white')
c.pack()
c.create_line(100, 180, 100, 50, fill='lightblue', width=90, arrow=LAST, arrowshape="50 50 20")
c.create_oval(150,5,190,45, fill='orange',outline='orange')
 
for i in range(0,200,10 ):
    grass(0,30)
 
root.mainloop()

from tkinter import *
 
root = Tk()
 
c = Canvas(root, width=200, height=265, bg='white')
 
c.create_polygon((50, 250), (150, 250), (150, 150), (165, 150), (100, 85), (35, 150), (50, 150), fill='lightblue')
 
c.create_oval(140, 40, 190, 90, fill='orange', outline='yellow')
 
for x in range(0, 201, 10):
    c.create_arc(0 + x, 225, 100 + x, 325, fill='green', start=135, extent=45, style=ARC)
 
c.pack()
 
root.mainloop()

Пока не додумался, как сделать через один класс, все-таки ооп такое оопээ...))
from tkinter import *
class Object:
    def __init__(self,Coords,color):
        self.Coords=Coords
        self.color=color
class Polyg(Object):
    def __init__(self, Coords, color):
        Object.__init__(self, Coords, color)
        self.obj = c.create_polygon(*self.Coords, fill=self.color)
class Oval(Object):
    def __init__(self, Coords, color):
        Object.__init__(self, Coords, color)
        self.obj= c.create_oval(*self.Coords, fill=self.color)
class Arc(Object):
    def __init__(self, Coords,start,extent,style, color1):
        Object.__init__(self, Coords, color1)
        self.color1=color1
        self.start=start
        self.extent=extent
        self.style=style
        self.obj= c.create_arc(*self.Coords,start=self.start,extent=self.extent,style=self.style, outline=self.color1)
root = Tk()
 
c = Canvas(root, width=200, height=200, bg='white')
c.pack()
roof_Coords=(100,20,50,60,150,60)
roof=Polyg(roof_Coords,'Black')
wall_Coords=(70,60,130,60,130,130,70,130)
wall=Polyg(wall_Coords,'Blue')
window_Coords=(80,70,100,70,100,90,80,90)
window=Polyg(window_Coords,'Yellow')
sun_Coords=(170,10,190,30)
sun=Oval(sun_Coords,'Yellow')
 
for i in range (30):
    grass_Coords=(i*10,170,i*10+10,200)
    grass=Arc(grass_Coords,240,-70,'arc','Green')
 
root.mainloop()
<python>

Ответ на от Вутмук

у класса карандаш есть методы нарисовать POLYGON,OVAL,ARC таким образом мы делаем код намного проще для понимания
from tkinter import *
root=Tk()
c = Canvas(root, width=200, height=200, bg='white')
 
class pencil:
	def draw_polygon(self,coords,color):
		self.obj=c.create_polygon(coords,fill=color)
	def draw_oval(self,coords,color):
		self.obj=c.create_oval(coords,fill=color)
	def draw_arc(self,coords,start,extent,style,outline):
		self.obj=c.create_arc(coords,start=start,extent=extent,style=style, outline=outline)
c.pack()
pencil=pencil()		
roof=pencil.draw_polygon((100,20,50,60,150,60),'Blue')
wall=pencil.draw_polygon((70,60,130,60,130,130,70,130),'Blue')
sun=pencil.draw_oval((170,10,190,30),'Yellow')
window=pencil.draw_polygon((80,70,100,70,100,90,80,90),'Yellow')
for i in range (30):
    grass_Coords=(i*10,170,i*10+10,200)
    grass=pencil.draw_arc(grass_Coords,240,-70,'arc','Green')
root.mainloop()

from tkinter import *
 
root = Tk()
 
c = Canvas(root, width = 200, height = 200, bg = 'white')
c.pack()
 
c.create_line((100, 180), (100,50), fill = 'lightblue',
              arrow = LAST, width = 90, arrowshape="50 50 20")
 
c.create_oval((140, 10),(190, 60), fill = 'yellow')
 
for i in range(0, 200, 10):
    c.create_arc(i, 180, 30+i, 300+i, start=160, extent=-70, style=ARC, outline='green', width=2)
 
 
root.mainloop()

Ответ на от Влад

from tkinter import *
root = Tk()
 
c = Canvas(root, width=200, height=250, bg='white')
c.pack()
 
#коробка
c.create_rectangle(50, 100, 150, 190, fill='lightblue', outline='lightblue')
 
#окно
c.create_rectangle(75, 125, 125, 165, fill='white', outline='grey70', width=2)
c.create_line(100, 125, 100, 165, fill='grey70', width=2)
 
#крыша
c.create_polygon((25, 100), (100, 50), (175, 100), fill='brown')
 
#солнце
c.create_oval(145, 20, 175, 50, fill='orange', outline='orange')
 
#лучи солнца
i=0
while i<360:
	c.create_arc(130, 5, 190, 65, start=i, extent=5, fill='orange', outline='orange')
	i=i+30
 
#трава
i=0
while i<int(c['width'])+50:
	c.create_arc(i, 150, i+150, 350, start=180, extent=-30, style=ARC, outline='green', width=3)
	i=i+10
 
root.mainloop()

Чет..ну и.. Вообщем, если кто хочет оформить все нормально и/или доработать - валяйте, интересно будет потом посмотреть :D
from tkinter import *
from random import random
 
class FieldM:
    def __init__(self, master, width=400, height=400):
 
        self.can = Canvas(master, width=width, height=height, bg='black')
        self.can.pack()
 
        master.bind('<Motion>', lambda event, m=master: self.move(event, m))
        master.bind('<Return>', lambda event, w=width, h=height: self.restart(event, w, h))
 
        self.restart("", width, height)
 
    def move(self, event, master):
        x = event.x
        y = event.y
        master.title(f"{x}x{y}")
 
    def restart(self, event, width, height):
 
        self.createSun(int(random() * int(self.can['width'])), width, height)
        self.createClouds(width, 80, 160, 40)
        self.createMounts(height)
        self.createLand(width, height, 350)
 
        self.createGrass(width, 2, 352)  # floors
 
        self.createHouse(width, height, 220)
        self.createHouse(width, height, 10)
 
        self.createGrass(width, 11, 365)  # floors
 
 
 
    def createBall(self, x, y, r, c):
        self.can.create_oval(x+r, y+r, x-r, y-r, fill=c, outline=c)
 
    def createSun(self, loc, h,w):
        self.can.create_rectangle(0-2, 0-2, w+2, h+2, fill="lightblue")
 
        self.can.create_oval(loc+20, 0+20, loc-20, 0-20, fill='yellow', outline='yellow', width=1)
 
        for i in range(180, 360, 10):
            self.can.create_arc(loc+40, 0+40, loc-40, 0-40, start=i, extent=1, outline='yellow', style='arc', width=25)
 
    def createCloudsCh1(self, x, y, mass):
        for i in range(8):
            x += (random()*(mass*2)-mass)
            y += random()*(mass) - (mass/3)
 
            self.createBall(x, y, mass, "white")
 
    def createCloudsCh2(self, width, floor):
        for i in range(int(width * (-1)), int(width * 2), int(width / 5)):
            r = random() * 20 - 10  # -10 - 10
            m = random() * 2 - 4  # -4 - 1
            self.createCloudsCh1(i, floor + r, 20 + m)  # x,y,mass
 
    def createClouds(self, width, start, end, step):
        for i in range(start, end, step):
            self.createCloudsCh2(width, i)
 
 
    def createMountsCh1(self, heightF, x1, x2, height):
        heightF = heightF - 20
        height = height
        x1 = x1
        x2 = x2
        xcen = int((x1+x2)/2)
 
        self.can.create_polygon((x1, heightF), (xcen, height), (x2, heightF), fill='lightgrey', outline='darkgrey', width=2)
 
        x1 = (x1 + xcen)/2
        x2 = (x2 + xcen)/2
        heightF = (heightF + height)/2
 
        self.can.create_polygon((x1, heightF), (xcen, height), (x2, heightF), fill='white')
 
    def createMounts(self, height):
        count = int(random()*100)
        x1=0
        x2=0
        for i in range(count):
            x1 += int(random()*10)
            x2 += x1 + int(random()*(100-40)-40)
            h = int(random()*(250-150)+150)
            self.createMountsCh1(height, x1, x2, h)
 
    def createLand(self, widthF, heightF, height):
        self.can.create_rectangle(0, heightF, widthF, height, fill='lightgreen', width=0)
 
    def createWindow(self, width, height, x, y):
        x1 = x
        y1 = y
        x2 = x+width
        y2 = y+height
        xc = int((x+x+width)/2)
        yc = int((y+y+width)/2)
        xs = int((x2-x1)/2)
        ys = int((y2-y1)/2)
 
        self.can.create_rectangle(x, y, x+width, y+height, outline='lightsalmon3', fill='lightsalmon2', width=2)
 
        for i in (range(x1, x2, xs)):
            for j in (range(y1, y2, ys)):
                self.can.create_rectangle(i+1, j+1, i+ys-2, j+ys-2, outline='deepskyblue3', fill='deepskyblue2')
 
    def createRoof(self, x, y, height):
        hood = 15
        width = 150 #= x1-x2 from createHouse
 
        self.can.create_rectangle(x+width-20, y-5,
                                  x+width-30, y-height-10,
                                  width=0, fill='brown')
 
        self.can.create_polygon(x-hood, y,
                                x+10, y-height,
                                x+width-10, y-height,
                                x+width+hood, y)
 
    def createHouse(self, widthF, heightF, x):
        self.master = self.can
 
        x1 = x
        x2 = x1+150
        y1 = heightF - 40
        y2 = heightF - 100 - 40
 
        self.can.create_rectangle(x1, y1, x2, y2, fill='grey', width=0)
 
        for j in range(y1, y2, -4):
            for i in range(x1, x2, 10):
                self.can.create_rectangle(i, j-3, i+9, j, fill='brown', width=0)
 
        self.can.create_rectangle(x1 + 20, y1, x1 + 50, y1 - 60, fill='orange4', width=0)
        self.can.create_rectangle(x1 + 22, y1, x1 + 48, y1 - 58, fill='darkorange4', width=0)
 
        self.can.create_oval(x1 + 24, y1-30, x1 + 26, y1 - 32)
 
        self.createWindow(50, 50, x1+75, y1-65)
 
        self.createRoof(x1, y2+20, 30)
 
    def createPlant(self, height, x, y):
        w = height/8
        self.can.create_polygon(x+1*w, y,
                                  x, y-height/3*w,
                                  x+3*w, y-height*w,
                                  x+1*w, y-height/4*w,
                                  x+2*w, y,
                                fill='darkgreen', width=0
        )
 
    def createGrass(self, width, floors, y):
        stepx = 6
        stepy = 6
        n = 2
 
        for j in range(0,floors,1):
            for i in range(-10*width, width, stepx):
                self.createPlant(11, i+n, y+stepy*j)
            n += n
 
 
if __name__ == '__main__':
    root = Tk()
    FieldM(root)
    root.mainloop()

#подключаем tkinter
import tkinter
#создаем главное окно
root = tkinter.Tk()
#создаем виджет(холст 640*480 белый)
canvas = tkinter.Canvas(root, width = 640, height = 480, bg = "white")
canvas.pack()
#рисуем на виджете
#
#солнышко
canvas.create_oval((420,50),(520,150), fill = "orange", outline = "orange")
#домик
canvas.create_polygon((100,240),(300,140),(500,240), fill = "lightblue")
canvas.create_rectangle((130,240),(470,430), fill = "lightblue",
                        outline = "lightblue")
#травка, через цикл
x_start = 0
while x_start < 600:
    #отрисовка травинки
    canvas.create_arc((x_start,400),(x_start+100,500), start = 180,
                      extent = -80, style = "arc", outline = "green", width = 5)
    #следующая травинка с "шагом" 35 пикселей
    x_start = x_start + 35
#ожидание событий
root.mainloop()