상세 컨텐츠

본문 제목

[Python 파이썬 독학 활용2편 3일차] GUI(tkinter) - 3-2

파이썬 스터디/파이썬-Python 활용편2

by 후즈테크 2021. 8. 4. 17:57

본문

반응형

23. 파일 추가 & 선택 삭제 & 24. 저장 경로

    : '파일추가' 와 '선택삭제' 버튼의 기능 활성화

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


root = Tk()
root.title("WT GUI")

# 파일 추가
def add_file():
    files = filedialog.askopenfilenames(title ="이미지 파일을 선택하세요", \
        filetypes=(("PNG 파일", "*.png"),("모든 파일", "*.*")), \
            #initialdir="C:/") # 최초에 C:/ 경로를 보여줌
            initialdir=r"D:\personal\study") # 경로 스트링 정상적으로 나옴 탈출 문자 예외

    # 사용자가 선택한 파일 목록
    for file in files:
        list_file.insert(END, file)




# 선택삭제
def del_file():
    # 앞에서 부터 지우면 인덱스번호가 달라짐. 뒤에서 부터 삭제
    for index in reversed(list_file.curselection()):
        list_file.delete(index)


# 저장 경로(폴더)
def browse_dest_path():
    forlder_selected = filedialog.askdirectory()
    if forlder_selected =='':
        return
    #print(forlder_selected)
    txt_dest_path.delete(0, END)
    txt_dest_path.insert(0, forlder_selected)


# 시작
def start():
    # 각 옵션들 값을 확인
    # print("가로 넓이 : ", cmb_width.get())
    # print("간격 : ", cmb_space.get())
    # print("포맷 : ", cmb_format.get())

    # 파일 목록 확인
    if list_file.size() ==0:
        msgbox.showwarning("경고", "이미지 파일을 추가하세요.")
        return
    
    # 저장 경로 확인
    if len(txt_dest_path.get()) ==0:
        msgbox.showwarning("경고", "저장 경로를 선택하세요.")
        return
    

# # 파일 프레임(파일 추가, 선택 삭제)

file_frame = Frame(root)
file_frame.pack(fill="x", padx=5, pady=5)

btn_add_file = Button(file_frame, padx=5, pady=5, width=12, text ="파일추가", command=add_file)
btn_add_file.pack(side="left")

btn_del_file = Button(file_frame, padx=5, pady=5, width=12, text="선택삭제", command=del_file)
btn_del_file.pack(side="right")

# 리스트 프레임
list_frame = Frame(root)
list_frame.pack(fill="both", padx=5, pady=5)

scrollbar = Scrollbar(list_frame)
scrollbar.pack(side="right", fill="y")

list_file = Listbox(list_frame, selectmode="extended", height=15, yscrollcommand=scrollbar.set)
list_file.pack(side="left", fill="both", expand=True)
scrollbar.config(command=list_file.yview)

# 저장 경로 프레임
path_frame = LabelFrame(root, text="저장경로")
path_frame.pack(fill="x", padx=5, pady=5, ipady=5)

txt_dest_path = Entry(path_frame)
txt_dest_path.pack(side="left", fill="x",padx=5, pady=5,expand=True, ipady=4)

btn_dest_path = Button(path_frame, text="찾아보기", width=10, command=browse_dest_path)
btn_dest_path.pack(side="right", padx=5, pady=5)


# 옵션 프레임
frame_option = LabelFrame(root, text="옵션")
frame_option.pack(padx=5, pady=5, ipady=5)


#1. 가로 넓이 옵션

# 가로 넓이 레이블
lbl_width = Label(frame_option, text ="가로넓이" , width=8)
lbl_width.pack(side="left", padx=5, pady=5)

# 가로 넓이 콤보

opt_width = ["원본유지", "1024", "800", "640"]
cmb_width = ttk.Combobox(frame_option, state="readonly", values = opt_width, width=10)

cmb_width.current(0)
cmb_width.pack(side="left", padx=5, pady=5)


#2. 간격 옵션

# 간격 옵션 레이블

lbl_space = Label(frame_option, text ="간격" , width=8)
lbl_space.pack(side="left", padx=5, pady=5)

# 간격 옵션 콤보
opt_space = ["없음", "좁게", "보통", "넓게"]
cmb_space = ttk.Combobox(frame_option, state="readonly", values = opt_space, width=10)

cmb_space.current(0)
cmb_space.pack(side="left", padx=5, pady=5)



#3. 파일 포맷 옵션

# 파일포맷 옵션 레이블

lbl_format = Label(frame_option, text ="포맷" , width=8)
lbl_format.pack(side="left", padx=5, pady=5)

# 간격 옵션 콤보
opt_format = ["PNG","JPG","BMP"]
cmb_format = ttk.Combobox(frame_option, state="readonly", values = opt_format, width=10)

cmb_format.current(0)
cmb_format.pack(side="left", padx=5, pady=5)


# 진행상황 progress Bar
frame_progress = LabelFrame(root, text="진행상황")
frame_progress.pack(fill="x", padx=5, pady=5, ipady=5)


p_var = DoubleVar()
progress_bar = ttk.Progressbar(frame_progress, maximum=100, variable=p_var)
progress_bar.pack(fill="x", padx=5, pady=5)


# 실행 프레임
frame_run = Frame(root)
frame_run.pack(fill="x", padx=5, pady=5)


btn_close = Button(frame_run, padx=5, pady=5, text="종료", width=12, command=root.quit)
btn_close.pack(side="right", padx=5, pady=5)

btn_start = Button(frame_run, padx=5, pady=5, text="시작", width=12 , command=start)
btn_start.pack(side="right", padx=5, pady=5)



root.resizable(False,False) # x너비, y 변경 불가
root.mainloop()

주의사항

 - files = filedialog.askopenfilenames(title ="이미지 파일을 선택하세요", \
        filetypes=(("PNG 파일", "*.png"),("모든 파일", "*.*")), \
        initialdir=r"D:\personal\study") # 경로 스트링 정상적으로 나옴 탈출 문자 예외

    : filedialog.askopenfilenames 를 통해 file 을 추가할 수 있다.

    : filetypes 를 설정하여 원하는 확장자만 구별할 수 있다.

    : r"D:\personal\study" 와 같이 'r' 을 입력하게 되면 '\' 등이 탈출문자 등으로 잘못 입력되는 경우 없이 바로 입력가능하다.

 - for file in files:
    list_file.insert(END, file)

    : for 문을 이용하여 선택된 파일의 경로와 파일명을 list_file 의 마지막 부분에 추가한다.

 -
# 선택삭제
def del_file():
    for index in reversed(list_file.curselection()):
        list_file.delete(index)

    : reversed 해당 리스트의 값을 역순으로 정렬

반응형

Ex) 삭제 시, 리스트에 포함된 index 값 역순 정렬이 필요한 이유!!

( index 번호 / DATA ) 가 아래와 같을 때, DATA 2, 5 를 지우기 위해

index 2, 5 를 2번 부터 지우게 되면

실행 전 : (0 / 0), (1 / 1), (2 / 2), (3 / 3), (4 / 4), (5 / 5) ,(6 / 6)

index 2삭제 : (0 / 0), (1 / 1), (2 / 3), (3 / 4), (4 / 5) ,(5 / 6)

index 5삭제 : (0 / 0), (1 / 1), (2 / 3), (3 / 4), (4 / 5)

가 실행되며, 실제 지우려 했던 DATA 5 가 지워지지 않고 다른 값이 지워진다.

 

하지만 index의 역순으로 삭제하게 되면 

실행 전 : (0 / 0), (1 / 1), (2 / 2), (3 / 3), (4 / 4), (5 / 5) ,(6 / 6)

index 5삭제 : (0 / 0), (1 / 1), (2 / 2), (3 / 3), (4 / 4), (5 / 6)

index 2삭제 : (0 / 0), (1 / 1), (2 / 3), (3 / 4), (4 / 6)

로 정상적으로 값을 지울 수 있다.

 

    : curselection() 으로 선택된 항목의 index 번호를 알 수 있다.

    : index 번호를 이용하여 여러개를 항목을 삭제할 경우에는

     앞에서 부터 지우면 인덱스번호가 달라지기 때문에. 뒤에서 부터 삭제한다!!

 

 

- def browse_dest_path():
    forlder_selected = filedialog.askdirectory()
    if forlder_selected =='':
        return
    txt_dest_path.delete(0, END)
    txt_dest_path.insert(0, forlder_selected)

    : filedialog.askdirectory() 해당 폴더 경로 반환

    : forlder_selected =='' 취소 눌렀을 경우 아무런 동작을 하지 않도록 if 문 작성

 

 - def start():
    # 파일 목록 확인
    if list_file.size() ==0:
        msgbox.showwarning("경고", "이미지 파일을 추가하세요.")
        return
    
    # 저장 경로 확인
    if len(txt_dest_path.get()) ==0:
        msgbox.showwarning("경고", "저장 경로를 선택하세요.")
        return

 

    : 파일 선택 및 저장 경로 선택이 안 될 경우 시작하지 않도록 조건 추가.

반응형

관련글 더보기

댓글 영역