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

독학 Python tkinter(GUI) - 11.Entry2(+filedialog)

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

오늘은 지난 포스팅에서 예고한 entry 2번째 이야기, 활용편이다.

 

보통 entry는 사용자의 입력을 받기 위해 사용한다는 것을 이제 모두가 알텐데

특정 폴더 경로나 파일 이름 등을 사용자가 직접 입력한다면,

사용자가 오타로 인해 잘못 입력할 수도 있고,

다른 내용을 타이핑 하던 중 의도치 않게 수정이 될 수도 있다.

 

이런 상황을 유연하게 대처하기 위해 몇가지 entry에 몇가지 설정과 과정을 더해주면

좀 더 오류를 줄이고 사용도 편리한 GUI 환경을 구성할 수 있다.

 

1. entry 수정 가능 / 불가능

 - 사용자의 입력을 받기 위한 entry의 값을 수정 불가능하게 한다는게 뜬금 없는 말처럼 느껴질 수 있다.

 - 하지만 실제로 마지막 결과물을 본다면 참 유용하게 사용할 수 있겠구나 라는 생각이 들 것이다.

 - 사용 방법은 어렵지 않다. 해당 entry 의 state 파라미터를 [normal, disable]로 구분해주면 된다. 

   (config의 기본 state 값은 normal(수정 가능 상태) 이다.)

from tkinter import *
import tkinter.messagebox as msb


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


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

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

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

id_label = Label(body_frame, text = 'ID : ')
id_label.pack()

id_input_entry = Entry(body_frame)
id_input_entry.insert(0,'ID를 입력하세요.')
id_input_entry.pack()

pw_label = Label(body_frame, text='PW를 입력하세요.')
pw_label.pack()

pw_input_entry = Entry(body_frame, show='*')
pw_input_entry.pack()

source_path_label = Label(body_frame, text='자료 경로를 지정하세요.')
source_path_label.pack()

source_path_entry = Entry(body_frame)
source_path_entry.config(state="disable")  
source_path_entry.pack()

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

 - 위 코드는 33라인의 source_path_entry.config(state='disable') 이라는 한줄의 코드 추가로 인해 내용이 입력되지 않는다.

 - 그럼 사용자가 입력도 못하는 entry를 어떻게 활용할 것인가? 바로 앞에서 배운 버튼과 연계하는 방식이다.

 

2. 상태창 확인 버튼과 연결하기

  - entry 요소의 state 상태를 확인하기 위해 entry를 생성할 때 input_state라는 속성(attribute)값을 추가한다.

  - 조건문을 통해 해당 값을 확인하고 state를 교차로 변경할 수 있다.

 

from tkinter import *
import tkinter.messagebox as msb


def state_change():
    if source_path_entry.input_state == 'disable':
        print('normal로 변경합니다.')
        source_path_entry.input_state = 'normal'
        source_path_entry.config(state='normal')

    elif source_path_entry.input_state == 'normal':
        print('disable로 변경합니다.')
        source_path_entry.input_state = 'disable'
        source_path_entry.config(state='disable')

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


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

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

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

id_label = Label(body_frame, text = 'ID : ')
id_label.pack()

id_input_entry = Entry(body_frame)
id_input_entry.insert(0,'ID를 입력하세요.')
id_input_entry.pack()

pw_label = Label(body_frame, text='PW를 입력하세요.')
pw_label.pack()

pw_input_entry = Entry(body_frame, show='*')
pw_input_entry.pack()

source_path_label = Label(body_frame, text='자료 경로를 지정하세요.')
source_path_label.pack()

source_path_entry = Entry(body_frame)
source_path_entry.input_state = 'disable' # 상태 확인을 위한 임의의 attribute 추가
source_path_entry.config(state="disable")  
source_path_entry.pack()

state_change_btn = Button(body_frame, text='상태 변경', command=state_change)
state_change_btn.pack()

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

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

  - [상태 변경] 버튼을 누를 때 마다, state_change 메서드를 호출한다.

   : 호출 시에 임의로 우리가 생성한 entry.input_state 속성 값을 확인하여 해당 entry의 state 값을 변경한다.

 

 

3. filedialog 사용하기

  - 우리는 폴더나 파일을 찾을 때도 GUI를 이용하는 방법이 더 익숙하다.

  - 아래의 그림과 같은 폴더를 선택하는 창을 우리가 직접 만드는 고생 없이 filedialog 를 불러오면 사용이 가능한다. 

 

 1) 폴더 선택하기 

  - 먼저 3라인과 같이 filedialog 라이브러리를 호출해준다.

  - 그리고 get_folder 메서드를 만들어 주는데,

     GUI를 통해 선택될 폴더의 경로를 get_folder_path 변수에 저장하는 간단한 함수이다.

     아래의 if문의 경우, 취소 버튼을 눌렀을 때의 동작을 처리 하기 위함으로

     정상적으로 입력이 되면 우리가 disable로 설정해두었던 view_folder_path를 normal 로 변경한 후 

     GUI에서 입력 받은 경로를 입력하고,

   - 취소를 누르면 아무런 동작도 하지 않는다.

  * normal 과 disable의 제어 또한 하나의 메서드로 처리하면 해당 함수를 호출시에만 수정이 가능하고

    사용자의 실수로 수정되는 오류나 입력등을 제어할 수 있다. 

from tkinter import *
import tkinter.messagebox as msb
from tkinter import filedialog # 파일 open 기능 사용


def get_folder():
    get_folder_path = filedialog.askdirectory()
    
    #global load_origin_image_path_entry
    
    if len(get_folder_path) > 0:
        view_folder_path.config(state="normal")
        view_folder_path.delete(0, END)

        view_folder_path.insert(END, get_folder_path)
        view_folder_path.config(state="disable")




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


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

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

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

id_label = Label(body_frame, text = 'ID : ')
id_label.pack()

id_input_entry = Entry(body_frame)
id_input_entry.insert(0,'ID를 입력하세요.')
id_input_entry.pack()

pw_label = Label(body_frame, text='PW를 입력하세요.')
pw_label.pack()

pw_input_entry = Entry(body_frame, show='*')
pw_input_entry.pack()

source_path_label = Label(body_frame, text='자료 경로를 지정하세요.')
source_path_label.pack()

source_path_entry = Entry(body_frame)
source_path_entry.config(state="disable")  
source_path_entry.pack()

get_folder_btn = Button(body_frame, text='찾아보기', command=get_folder)
get_folder_btn.pack()

view_folder_path = Entry(body_frame)
view_folder_path.pack()


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

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

반응형

 - 해당 GUI가 더 깔끔하게 보일 수 있도록 grid를 이용해 정렬시켜보면

from tkinter import *
import tkinter.messagebox as msb
from tkinter import filedialog # 파일 open 기능 사용


def get_folder():
    get_folder_path = filedialog.askdirectory()
    
    #global load_origin_image_path_entry
    
    if len(get_folder_path) > 0:
        view_folder_path.config(state="normal")
        view_folder_path.delete(0, END)

        view_folder_path.insert(END, get_folder_path)
        view_folder_path.config(state="disable")




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


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

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

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

id_label = Label(body_frame, text = 'ID : ')
id_label.grid(column=1, row=1, sticky='NEWS')

id_input_entry = Entry(body_frame)
id_input_entry.insert(0,'ID를 입력하세요.')
id_input_entry.grid(column=2, row=1)


pw_label = Label(body_frame, text='PW를 입력하세요.')
pw_label.grid(column=1, row=2)

pw_input_entry = Entry(body_frame, show='*')
pw_input_entry.grid(column=2, row=2)

source_path_label = Label(body_frame, text='자료 경로를 지정하세요.')
source_path_label.grid(column=1, row=3, columnspan=2, sticky='NEWS')

source_path_entry = Entry(body_frame)
source_path_entry.config(state="disable")  
source_path_entry.grid(column=1, row=4, columnspan=2, sticky='NEWS')

get_folder_btn = Button(body_frame, text='찾아보기', command=get_folder)
get_folder_btn.grid(column=1, row=5, sticky='NEWS')

view_folder_path = Entry(body_frame)
view_folder_path.grid(column=2, row=5)


quit_btn = Button(body_frame, text='종료', command=quit)
quit_btn.grid(column=1, row=6, columnspan=2, sticky='NEWS')

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

 

 

 2) 파일 선택하기

from tkinter import *
import tkinter.messagebox as msb
from tkinter import filedialog # 파일 open 기능 사용


def get_folder():
    get_folder_path = filedialog.askdirectory()
    
    #global load_origin_image_path_entry
    
    if len(get_folder_path) > 0:
        view_folder_path.config(state="normal")
        view_folder_path.delete(0, END)

        view_folder_path.insert(END, get_folder_path)
        view_folder_path.config(state="disable")

def get_file():
    get_file_path = filedialog.askopenfilename(title ="Excel 파일을 선택하세요", \
    filetypes=(("Excel 파일", "*.xlsx"),("모든 파일", "*.*")), \
        #initialdir="C:/") # 최초에 C:/ 경로를 보여줌
        initialdir=r"./") # 경로 스트링 정상적으로 나옴 탈출 문자 예외
    if len(get_file_path) > 0:
        view_file_path.config(state="normal")
        view_file_path.delete(0, END)

        view_file_path.insert(END, get_file_path)
        view_file_path.config(state="disable")

    


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


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

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

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

id_label = Label(body_frame, text = 'ID : ')
id_label.grid(column=1, row=1, sticky='NEWS')

id_input_entry = Entry(body_frame)
id_input_entry.insert(0,'ID를 입력하세요.')
id_input_entry.grid(column=2, row=1)


pw_label = Label(body_frame, text='PW를 입력하세요.')
pw_label.grid(column=1, row=2)

pw_input_entry = Entry(body_frame, show='*')
pw_input_entry.grid(column=2, row=2)

source_path_label = Label(body_frame, text='자료 경로를 지정하세요.')
source_path_label.grid(column=1, row=3, columnspan=2, sticky='NEWS')

source_path_entry = Entry(body_frame)
source_path_entry.config(state="disable")  
source_path_entry.grid(column=1, row=4, columnspan=2, sticky='NEWS')

get_folder_btn = Button(body_frame, text='폴더 찾아보기', command=get_folder)
get_folder_btn.grid(column=1, row=5, sticky='NEWS')

view_folder_path = Entry(body_frame)
view_folder_path.grid(column=2, row=5)



get_file_btn = Button(body_frame, text='파일 찾아보기', command=get_file)
get_file_btn.grid(column=1, row=6, sticky='NEWS')

view_file_path = Entry(body_frame)
view_file_path.grid(column=2, row=6)


quit_btn = Button(body_frame, text='종료', command=quit)
quit_btn.grid(column=1, row=7, columnspan=2, sticky='NEWS')

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

 

  - 파일 검색도 get_folder 메서드와 비교시 큰 차이점은 없다.

  - filedialog 라이브러리의 askopenfilename 메서드의 결과 값을 get_file_path에 저장하는데,

    filetypes 의 설정을 지정하면 아래와 같이 특정 확장자만 선택할 수 있다.

  - 기본 경로 또한 현재 폴더 또는 특정 폴더를 지정해주면 해당 메서드를 호출했을 때의 결과값을 GUI상에 표현할 수 있게 된다.

 

 

이쁘진 않아도 뭔가 구색이 갖춰져가는 듯한 느낌을 받고 있으신가요?

이제 정말 몇가지 남지 않았습니다.

 

조금만 더 화이팅!! 

반응형