본문 바로가기
Python/GUI(tkinter)

독학 Python tkinter(GUI) - 17.progressbar

by To올라운더 2023. 11. 15.
반응형

진행 상태를 알려주는 GUI로 Label 의 값을 계속 변경해 줄 수도 있지만,

좀 더 시각적이고 가시적으로 보여주기위해서는 progressbar를 이용해보는게 좋다.

1. 코드

 - 이번에도 tkiner.ttk 라이브러리를 사용한다.

 - 단순히 Progressbar 객체(위젯)를 생성하는 것은 한두 줄의 코드로 되지만,

   우리가 원하는 것처럼 진행하기 위해서는 몇가지 옵션이 필요하다.

 

 - 파라미터별 비교를 위해 progressbar1~3을 각각 만들었다.

from tkinter import *
import tkinter.ttk

root = Tk()
root.title('To올라운드의 알찬 GUI 강의')

root.geometry("300x500") # 가로 X 세로 / 대문자X 하면 실행안됨

#msb.showinfo('Welcome','안녕하세요. To올라운더와 함께 하는 GUI입니다.')

def progressbar_start():
    
    #progressbar1.start()
    progressbar2.start(1000) # 1000 ms 마다 움직임, 1000ms = 1s
    progressbar3.start(1000)
    

def progressbar_stop():
    progressbar1.stop() 
    progressbar2.stop()
    progressbar3.stop()
    

body_frame = Frame(root, relief='solid', bd=2, background='orange', padx=5, pady=5)
body_frame.pack(fill='both', expand=True)

progressbar1_label = Label(body_frame, text='Progressbar1')
progressbar1_label.pack()
progressbar1 = tkinter.ttk.Progressbar(body_frame, maximum=100, mode='indeterminate')
progressbar1.pack()


progressbar2_label = Label(body_frame, text='Progressbar2 / mode = indeterminat')
progressbar2_label.pack()
progressbar2 = tkinter.ttk.Progressbar(body_frame, maximum=100, mode='indeterminate')
progressbar2.pack()


progressbar3_label = Label(body_frame, text='Progressbar3 / mode = determinat')
progressbar3_label.pack()
progressbar3 = tkinter.ttk.Progressbar(body_frame, maximum=100, mode='determinat')
progressbar3.pack()


progressbar_start_btn = Button(body_frame, text='진행바 시작', command=progressbar_start)
progressbar_start_btn.pack(fill='x')

progressbar_stop_btn = Button(body_frame, text='진행바 중지', command=progressbar_stop)
progressbar_stop_btn.pack(fill='x')

quit_btn = Button(body_frame, text='종료', command=quit)
quit_btn.pack(fill='x')


root.resizable(False,False) # x너비, y 변경 허용 여부
root.mainloop()

 

반응형

  - progressbar1~3을 비교해보면

  - progressbar1 은 progressbar_start 메서드에서 주석처리가 되어 start를 진행하지 않는다.

    당연히, 멈춰있고 아무런 반응이 없는데 progressbar는 start와 stop 메서드에 따라 동작하게 된다.

  - progressbar2 의 경우, indeterminate mode를 사용 중인데, 첨부된 동영상에서 보듯이

    진행률이 진행됨에 따라 진행커서(초록색)이 움직이게 된다.

  - 대신 determinate mode를 지정한 progressbar3의 경우에는

    진행률이 진행됨에 따라 진행커서(초록색) 영역이 확장되며 채워진다.

 

  - 그 외에도 공통적인 사항으로 start와 stop 메서드가 있는데,

    start 메서드의 경우, 전달되는 값에 따라 ms 단위로 진행바가 움직인다. 1000을 입력하게 되면 1초마다 움직이고, 숫자가 작아질수록 더 빨리 움직인다.

  - 그런데, stop을 하지 않고 기다려보면 progressbar가 계속 움직이는 것을 볼 수 있는데, 수동으로 stop을 할 수도 있지만

    우리가 원하는 진행 상태를 확인하기 위해서는 특정 변수와 연결시켜야한다.

 

 

2. 응용하기

from tkinter import *
import tkinter.ttk
import time

root = Tk()
root.title('To올라운드의 알찬 GUI 강의')

root.geometry("300x500") # 가로 X 세로 / 대문자X 하면 실행안됨

#msb.showinfo('Welcome','안녕하세요. To올라운더와 함께 하는 GUI입니다.')

def progressbar_start():
    
    #progressbar1.start()
    progressbar2.start(10) # 1000 ms 마다 움직임, 1000ms = 1s
    progressbar3.start(10)
    

def progressbar_stop():
    progressbar1.stop() 
    progressbar2.stop()
    progressbar3.stop()
    

body_frame = Frame(root, relief='solid', bd=2, background='orange', padx=5, pady=5)
body_frame.pack(fill='both', expand=True)

progressbar1_label = Label(body_frame, text='Progressbar1')
progressbar1_label.pack()
progressbar1 = tkinter.ttk.Progressbar(body_frame, maximum=100, mode='indeterminate')
progressbar1.pack()


progressbar2_label = Label(body_frame, text='Progressbar2 / mode = indeterminat')
progressbar2_label.pack()
progressbar2 = tkinter.ttk.Progressbar(body_frame, maximum=100, mode='indeterminate')
progressbar2.pack()


progressbar3_label = Label(body_frame, text='Progressbar3 / mode = determinat')
progressbar3_label.pack()
progressbar3 = tkinter.ttk.Progressbar(body_frame, maximum=100, mode='determinat')
progressbar3.pack()

# 변수와 진행률 연동하기
def increse_success_rate():
    for i in range(0, 101):
        time.sleep(0.01)

        success_rate.set(i) # progressbar value 값 설정
        progressbar4.update() # 변경된 value 값이 progressbar 에 적용(미사용시 동작 안됨)

    time.sleep(5)

success_rate = DoubleVar() # 소수점 단위처리를 위해 Double 사용

progressbar4_label = Label(body_frame, text='Progressbar4 / 변수 연동')
progressbar4_label.pack()
progressbar4 = tkinter.ttk.Progressbar(body_frame, maximum=100, mode='determinat', variable=success_rate)
progressbar4.pack()


progressbar_start_btn = Button(body_frame, text='진행바 시작', command=progressbar_start)
progressbar_start_btn.pack(fill='x')

progressbar_stop_btn = Button(body_frame, text='진행바 중지', command=progressbar_stop)
progressbar_stop_btn.pack(fill='x')

progressbar4_run_btn = Button(body_frame, text='진행바4 시작', command=increse_success_rate)
progressbar4_run_btn.pack(fill='x')

quit_btn = Button(body_frame, text='종료', command=quit)
quit_btn.pack(fill='x')


root.resizable(False,False) # x너비, y 변경 허용 여부
root.mainloop()

  

 - progressbar4 를 새로 생성할 때 variable 변수를 사용한다.

 

 - 시간 딜레이를 주기위해 time 라이브러리를 사용하였는데,

   해당 시간(초) 동안 프로그램이 대기하는 기능이다.

 

 - 소수점 단위 처리를 위해 DoubleVar() 로 생성하였는데, 

   예시 코드처럼 i 값이 변하는 것에 따라 적용하는 방법도 있지만,

   예를 들어 전체 건수 2000 건 중 현재 진행 상태에 따라 해당 값을 반복해서 넣어주어도 진행 상태가 처리된다.

   (1번째 처리 1/2000, 2번째 처리 2/2000 ........1000번째 처리 1000/2000) 이런 식의 값을 i에 할당하면된다.

 

 - 51라인과 같이 해당 변수 값이 변할 때 해당 progressbar에 update를 진행해주면 해당 값이 반영된다.

 

 - 마지막 완료 후, 전체 progressbar가 5초 멈추는 것을 볼 수 있는데, increse_success_rate 메서드의 마지막에

   5초 delay가 할당되어 있기 때문이다.

 

  - 하나의 매서드가 멈춰도 다른 매서드가 동작하기 위해서는 Thread(쓰레드) 라는 기능을 알아야한다.

    (배워야 할 것이 점점 많아진다는 생각이 든다면 내 실력도 그만큼 늘어나고 있다는 걸 잊지말자.)

 

3. 그 외 옵션 파라미터

파라미터 의미 기본값 속성
length 프로그래스 바의 너비 100 상수
orient 프로그래스 바의 표시 방향 vertical vertical, horizontal
mode 프로그래스 바의 표시 스타일 determinate  determinate, indeterminate

 

반응형