프로그램/python

[파이썬] 파일 복사 GUI 형태로 만들기

더월드 2023. 12. 16.

아래는 Python에서 Tkinter를 사용하여 윈도우 형태의 GUI를 생성하고, 

사용자로부터 소스 폴더와 목적지 폴더를 입력받아 처리하는 간단한 예제 코드입니다.

 

- 두 개의 텍스트박스와 두 개의 버튼이 있는 GUI 창이 나타납니다.

- 첫 번째 텍스트박스에는 소스 폴더의 경로, 두 번째 텍스트박스에는 목적지 폴더의 경로를 입력할 수 있습니다.

- "처리하기" 버튼을 클릭하면 폴더 복사 또는 다른 원하는 작업을 수행할 수 있습니다.

import tkinter as tk
from tkinter import filedialog
import shutil
import os

def select_source_folder():
    folder_path = filedialog.askdirectory()
    source_folder_entry.delete(0, tk.END)
    source_folder_entry.insert(0, folder_path)

def select_destination_folder():
    folder_path = filedialog.askdirectory()
    destination_folder_entry.delete(0, tk.END)
    destination_folder_entry.insert(0, folder_path)

def process_folders():
    source_folder = source_folder_entry.get()
    destination_folder = destination_folder_entry.get()

    # 실제로 하고자 하는 작업을 여기에 추가
    try:
        # 예: 소스 폴더의 내용을 목적지 폴더로 복사
        shutil.copytree(source_folder, destination_folder)
        print("폴더 복사 완료")
    except Exception as e:
        print("에러 발생:", e)

if __name__ == '__main__':
    # 윈도우 생성
    window = tk.Tk()
    window.title("폴더 처리 예제")
    
    # 소스 폴더 관련 위젯
    source_folder_label = tk.Label(window, text="소스 폴더:")
    source_folder_label.grid(row=0, column=0, padx=10, pady=10, sticky=tk.E)
    
    source_folder_entry = tk.Entry(window, width=50)
    source_folder_entry.grid(row=0, column=1, padx=10, pady=10)
    
    source_folder_button = tk.Button(window, text="폴더 선택", command=select_source_folder)
    source_folder_button.grid(row=0, column=2, padx=10, pady=10)
    
    # 목적지 폴더 관련 위젯
    destination_folder_label = tk.Label(window, text="목적지 폴더:")
    destination_folder_label.grid(row=1, column=0, padx=10, pady=10, sticky=tk.E)
    
    destination_folder_entry = tk.Entry(window, width=50)
    destination_folder_entry.grid(row=1, column=1, padx=10, pady=10)
    
    destination_folder_button = tk.Button(window, text="폴더 선택", command=select_destination_folder)
    destination_folder_button.grid(row=1, column=2, padx=10, pady=10)
    
    # 처리 버튼
    process_button = tk.Button(window, text="처리하기", command=process_folders)
    process_button.grid(row=2, column=0, columnspan=3, pady=10)
    
    # GUI 실행
    window.mainloop()

 

  체크박스, 프로그레스바 추가

- 체크박스의 기능은 수정해야 합니다. 단순히 체크박스 기능을 넣었습니다.

- 복사 진행 확인을 위해 프로그레스바 UI를 추가함.

import tkinter as tk
from tkinter import filedialog
from tkinter import ttk  # ttk 모듈 추가
import shutil
import os

def select_source_folder():
    folder_path = filedialog.askdirectory()
    source_folder_entry.delete(0, tk.END)
    source_folder_entry.insert(0, folder_path)

def select_destination_folder():
    folder_path = filedialog.askdirectory()
    destination_folder_entry.delete(0, tk.END)
    destination_folder_entry.insert(0, folder_path)

def copy_selected_items():
    source_folder = source_folder_entry.get()
    destination_folder = destination_folder_entry.get()

    selected_items = [item_list[index] for index, var in enumerate(checkbox_vars) if var.get()]

    total_items = len(selected_items)
    progress_bar["maximum"] = total_items

    for index, item in enumerate(selected_items, start=1):
        item_path = os.path.join(source_folder, item)
        destination_path = os.path.join(destination_folder, item)

        try:
            if os.path.isdir(item_path):
                shutil.copytree(item_path, destination_path)
            else:
                shutil.copy2(item_path, destination_path)
        except Exception as e:
            print("에러 발생:", e)

        progress_bar["value"] = index
        window.update_idletasks()

    print("복사 완료")

if __name__ == '__main__':
    # 윈도우 생성
    window = tk.Tk()
    window.title("폴더 및 파일 복사 예제")
    
    # 소스 폴더 관련 위젯
    source_folder_label = tk.Label(window, text="소스 폴더:")
    source_folder_label.grid(row=0, column=0, padx=10, pady=10, sticky=tk.E)
    
    source_folder_entry = tk.Entry(window, width=50)
    source_folder_entry.grid(row=0, column=1, padx=10, pady=10)
    
    source_folder_button = tk.Button(window, text="폴더 선택", command=select_source_folder)
    source_folder_button.grid(row=0, column=2, padx=10, pady=10)
    
    # 목적지 폴더 관련 위젯
    destination_folder_label = tk.Label(window, text="목적지 폴더:")
    destination_folder_label.grid(row=1, column=0, padx=10, pady=10, sticky=tk.E)
    
    destination_folder_entry = tk.Entry(window, width=50)
    destination_folder_entry.grid(row=1, column=1, padx=10, pady=10)
    
    destination_folder_button = tk.Button(window, text="폴더 선택", command=select_destination_folder)
    destination_folder_button.grid(row=1, column=2, padx=10, pady=10)
    
    # 항목 목록 및 체크박스 생성
    item_list = ["폴더1", "폴더2", "파일1.txt", "파일2.txt"]
    checkbox_vars = [tk.IntVar() for _ in range(len(item_list))]
    
    for index, item in enumerate(item_list):
        checkbox = tk.Checkbutton(window, text=item, variable=checkbox_vars[index])
        checkbox.grid(row=index + 2, column=0, columnspan=3, padx=10, pady=5, sticky=tk.W)
    
    # 복사 버튼
    copy_button = tk.Button(window, text="복사하기", command=copy_selected_items)
    copy_button.grid(row=len(item_list) + 2, column=0, columnspan=3, pady=10)
    
    # 프로그레스바
    progress_bar = ttk.Progressbar(window, orient=tk.HORIZONTAL, length=300, mode='determinate')  # ttk 모듈 사용
    progress_bar.grid(row=len(item_list) + 3, column=0, columnspan=3, pady=10)
    
    # GUI 실행
    window.mainloop()

 

▶ 드래그앤 드롭 추가

- 폴더 입력 부분에 드래그앤드롭 기능을 넣었습니다.

- tkinter에서는 드래그앤드롭 기능을 지원하지 않습니다.

- 대신에 tkinterdnd2 모듈을 이용하여 드래그 앤 드롭을 구현하였습니다.

 

tk와 tkinterdnd2 라이브러리를 추가합니다.

pip install tk
pip install tkinterdnd2
import tkinter as tk
from tkinterdnd2 import TkinterDnD, DND_FILES
from tkinter import filedialog, ttk
import shutil
import os

def select_source_folder(event=None):
    folder_path = filedialog.askdirectory()
    source_folder_entry.delete(0, tk.END)
    source_folder_entry.insert(0, folder_path)

def select_destination_folder(event=None):
    folder_path = filedialog.askdirectory()
    destination_folder_entry.delete(0, tk.END)
    destination_folder_entry.insert(0, folder_path)

def copy_selected_items():
    source_folder = source_folder_entry.get()
    destination_folder = destination_folder_entry.get()

    selected_items = [item_list[index] for index, var in enumerate(checkbox_vars) if var.get()]

    total_items = len(selected_items)
    progress_bar["maximum"] = total_items

    for index, item in enumerate(selected_items, start=1):
        item_path = os.path.join(source_folder, item)
        destination_path = os.path.join(destination_folder, item)

        try:
            if os.path.isdir(item_path):
                shutil.copytree(item_path, destination_path)
            else:
                shutil.copy2(item_path, destination_path)
        except Exception as e:
            print("에러 발생:", e)

        progress_bar["value"] = index
        window.update_idletasks()

    print("복사 완료")

def on_drop(event, entry_widget):
    entry_widget.delete(0, tk.END)
    entry_widget.insert(0, event.data)

if __name__ == '__main__':
    # 윈도우 생성
    window = TkinterDnD.Tk()
    window.title("폴더 및 파일 복사 예제")
    
    # 소스 폴더 관련 위젯
    source_folder_label = tk.Label(window, text="소스 폴더:")
    source_folder_label.grid(row=0, column=0, padx=10, pady=10, sticky=tk.E)
    
    source_folder_entry = tk.Entry(window, width=50, bd=2, relief="groove")
    source_folder_entry.grid(row=0, column=1, padx=10, pady=10)
    
    source_folder_button = tk.Button(window, text="폴더 선택", command=select_source_folder)
    source_folder_button.grid(row=0, column=2, padx=10, pady=10)
    
    # 드래그 앤 드롭을 처리할 이벤트를 추가
    source_folder_entry.drop_target_register(DND_FILES)
    source_folder_entry.dnd_bind('<<Drop>>', lambda event: on_drop(event, source_folder_entry))
    
    # 목적지 폴더 관련 위젯
    destination_folder_label = tk.Label(window, text="목적지 폴더:")
    destination_folder_label.grid(row=1, column=0, padx=10, pady=10, sticky=tk.E)
    
    destination_folder_entry = tk.Entry(window, width=50, bd=2, relief="groove")
    destination_folder_entry.grid(row=1, column=1, padx=10, pady=10)
    
    destination_folder_button = tk.Button(window, text="폴더 선택", command=select_destination_folder)
    destination_folder_button.grid(row=1, column=2, padx=10, pady=10)
    
    # 드래그 앤 드롭을 처리할 이벤트를 추가
    destination_folder_entry.drop_target_register(DND_FILES)
    destination_folder_entry.dnd_bind('<<Drop>>', lambda event: on_drop(event, destination_folder_entry))
    
    # 항목 목록 및 체크박스 생성
    item_list = ["폴더1", "폴더2", "파일1.txt", "파일2.txt"]
    checkbox_vars = [tk.IntVar() for _ in range(len(item_list))]
    
    for index, item in enumerate(item_list):
        checkbox = tk.Checkbutton(window, text=item, variable=checkbox_vars[index])
        checkbox.grid(row=index + 2, column=0, columnspan=3, padx=10, pady=5, sticky=tk.W)
    
    # 복사 버튼
    copy_button = tk.Button(window, text="복사하기", command=copy_selected_items)
    copy_button.grid(row=len(item_list) + 2, column=0, columnspan=3, pady=10)
    
    # 프로그레스바
    progress_bar = ttk.Progressbar(window, orient=tk.HORIZONTAL, length=300, mode='determinate')
    progress_bar.grid(row=len(item_list) + 3, column=0, columnspan=3, pady=10)
    
    # GUI 실행
    window.mainloop()

댓글

💲 추천 글