본문 바로가기
Python/tkinter

[Python tkinter] tkinter 모듈을 이용한 GUI - 애니메이션 move() , after() , sleep() , update()

by dev수니 2021. 4. 8.
반응형

 

 

tkinter 모듈을 사용하여 애니메이션 효과를 줄 수 있다.

다각형의 객체를 생성하고 move()를 통해 조금씩 이동시키는 방식으로 애니메이션 효과를 줄 수 있다.

 

이때 시간지연 메서드가 필요한데 Canvas 내에 있는 메서드 after() time모듈 내의 메서드 sleep() 이 있다.

 


 

 1  move() 

 

move(객체,x,y) : 객체가로 x 만큼, 세로 y 만큼 이동하는 메서드이다.

 

 


 

 2  시간 지연 메서드 ( after() , sleep() )

 

after() 와  sleep() 둘다 일정시간 동안 프로그램을 지연시키는 메서드이다. 둘의 차이점은 다른 모듈에 위치해 있다는 점과 설정값의 시간이 다르다는 것이다.

 

sleep()
time모듈 내의 함수이다 s 단위로 설정한다. (1초면 1로 작성)
따라서 time모듈 import 후 사용해준다.
after()
tkinter 모듈 내의 Canvas 클래스 소속 함수이다. ms 단위로 설정한다. (1초면 1000으로 작성)
따라서 Canvas객체.after() 로 사용해준다.

 

 


 

 3  update()

 

Canvas 클래스 내의 메서드로 기존 그림을 지우고 새로운 그림을 그릴 수 있도록 설정해준다.

Canvas객체.update() 로 사용해준다.

 

 

 


 

 

 

# 공이 굴러가는 애니메이션

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from tkinter import *
from random import *
from time import *
 
win = Tk()     # 윈도우창을 생성
 
can = Canvas(win,width=400,height=400)  # 캔버스 생성
can.pack()     # 캔버스 배치
     
id1 = can.create_oval(10,10,50,50,fill='pink')    # 원 생성
 
for i in range(110):     # 110번 반복
     can.move(id1,3,0)   # id1 객체를 오른쪽3 아래0만큼이동시킴
     #sleep(0.02)  # 0.02 초 뒤에 실행 아래 after와 같은 효과임
     can.after(20# 0.02 초 뒤에 실행
     can.update()   # 기존 canvas삭제 후 새로 배치할 수 있게 설정
 
win.mainloop() # 윈도우창이 종료될 때까지 윈도우를 실행한다.
cs

 

저번 포스팅에서는 create_rectangle 을 이용해 사각형을 만들었는데 이번에는 oval 로 원을 생성해 주었다. 줄10에서 id1객체에 create_oval 로 원을 생성하였고 이를 for 문을 통해 줄12에서 애니메이션화 시켜주었다.

 

줄13에 id1객체 즉 원 객체를 오른쪽으로 3, 아래로 0만큼 이동시켰고 이를 after() 메서드를 사용해 일정시간 지연 후 실행되도록 하였다. 그리고 update() 메서드로 기존 canvas를 삭제하고 새로 배치할 수 있도록 설정해주었다. 

 

따라서 줄12에서 for문에 i가 0일 때 id1객체가 오른쪽으로 3만큼 이동하고 after에서 0.02초 만큼 프로그램이 멈춘다. 그리고 update에서 기존 canvas를 삭제하고 새로 배치될 수 있게 설정한다.

그리고 i가 1일 때 또 id1 객체가 3만큼 이동하고 after에서 0.02초만큼 지연된다. 그리고 update에서 다시 배치되도록 설정한다. 이게 110번 반복되어서 우리 눈에 원이 굴러가는 것처럼 보여지는 것이다.

 

 

 

 

 

 


 

 

# 방향키를 누르면 방향키대로 공이 굴러가는 애니메이션

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 모듈
from tkinter import *
from random import *
 
# 함수
def move_right(event):    # 오른쪽으로 이동하는 핸들러
     can.move(id1,5,0)
     print(can.coords(id1))
     can.update()    # 기존 canvas삭제 후 새로 배치할 수 있게 설정
 
def move_left(event):    # 왼쪽으로 이동하는 핸들러
     can.move(id1,-5,0)
     print(can.coords(id1))
     can.update()    # 기존 canvas삭제 후 새로 배치할 수 있게 설정
 
# main()
win = Tk()     # 윈도우창 생성
 
can = Canvas(win,width=400,height=400)  # 캔버스 객체생성
can.pack()     # 캔버스 배치
 
id1 = can.create_oval(10,10,50,50,fill='pink')    # 원 객체 생성
 
can.bind("<Left>",move_left)  # 방향키 ← 입력시 핸들러 실행
can.bind("<Right>",move_right)     # 방향키 → 입력시 핸들러 실행
can.focus_set()     # 키보드가 눌리면 포커스를 수정
 
win.mainloop() # 윈도우창이 종료될 때까지 윈도우를 실행한다.
cs

 

위의 예제에서 사용된 윈도우창과 캔버스를 동일하게 사용하고 키를 입력하면 함수가 실행되도록 코드를 작성해주었다. 

 

줄22를 보면 원의 크기는 10x10이고 초기 위치는 x좌표 50 y좌표 50에 위치한 곳이다. 

 

줄24에서 방향키 왼쪽을 누를 경우 핸들러로 설정해준 move_left 를 만나 줄11의 함수가 실행되 왼쪽으로 5씩 이동할 것이고 원 객체의 좌표가 찍힐 것이다. 그리고 줄14의 update() 메서드로 기존 canvas 삭제 후 새로 배치될 수 있게 세팅되고 함수가 끝나면 줄26에서 키보드 포커스를 수정해준다.

 

그리고 줄25에서 방향키 오른쪽을 누를 경우 move_right 를 만나 줄 6의 함수가 실행되 오른쪽으로 5식 이동하고 좌표가 찍힐 것이다. 그리고 update() 메서드로 canvas가 새로 세팅될 수 있게 설정되고 함수가 끝나면 줄 26에서 다시 키보즈 포커스를 수정해준다.

 

따라서 위의 코드를 실행시키면 다음과 같이 작동한다.

 

 

왼쪽 방향키와 오른쪽 방향키를 번갈아가며 눌러주었다. 

 

 

 


 

 

위의 코드를 클래스를 사용하여 작성하려면 어떻게 해야 할까?

 

다음 코드는 클래스를 적용시켜서 코드를 작성한 예제이다. 클래스를 적용시켜 작성해야 나중에 객체를 만들어 사용할 수 있고 각 객체에 설정값을 다르게 줄 수 있다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 모듈을 추가하는 공간
from tkinter import *
from random import *
from time import *
# 시간에 관한 모듈
 
color = ['red''orange','yellow','pink','white','black']
 
# 클래스
class Ball:
     def __init__(self,x,y,can):
          self.x = x
          self.y = y
          self.color = choice(color)
          self.can = can
          self.ball = self.can.create_oval(self.x,self.y,50,50,fill=self.color)
          print("볼 생성")
 
     # 이동할 때 메서드
     def move_left(self,event):
          can.move(self.ball,-5,0)
          can.after(10)
          can.update()
 
     def move_right(self,event):
          can.move(self.ball,5,0)
          can.after(10)
          can.update()
          
# main()
win = Tk()     # 윈도우창을 생성
 
can = Canvas(win,width=400,height=400# 캔버스 생성
can.pack()    # 캔버스 배치
 
b1 = Ball(10,10,can)    # 객체 생성 x값, y값, canvas객체를 인수로 전달
 
can.bind("<Left>",b1.move_left)
can.bind("<Right>",b1.move_right)
can.focus_set()
 
win.mainloop() # 윈도우창이 종료될 때까지 윈도우를 실행한다.
cs

 

 

 

 

 

 

반응형

댓글