me

[python/development] project Handy 설치 및 개발 완료
2024.01.09 / , ,

핸디 로고

project Handy 응용프로그램 개발 이유는 업무상 수동으로 입력하는 부분이 여러 곳이다 보니 빠뜨리는 실수가 발생할 수 있어서… 자동화해 놓으면 아무래도 사람이 하는 실수가 적어지니.. 그걸 줄이려고 만들었다.

또 개발 때는 몰랐는데 이후 사용자에게서 인수인계에 원할하다는 피드백을 받았다.


project Handy 개발을 위한 기본 설치

D:\Python\python311\python -m venv vHandy

python.exe -m pip install --upgrade pip

pip install packaging

pip install openpyxl

pip install pandas

pip install python-tkdnd

pip install xlwings

project Handy – python UI 라이브러리 CustomTkinter

그 전에 python 테스트용 응용프로그램을 만들 때는 pyqt5를 사용했었다. 유지보수에도 pyqt5를 사용 중이었다.

그런데 Designer 프로그램을 써서 만들어도 어려웠다. 탭 하나 만들면 넣어야 하는 값이 왜 이렇게 많은지 ㅠㅠ.

또 미세하게 한 칸 올리면 내가 원하는 높이가 아니라서 파이썬 파일에서 수치를 수정해서 다시 UI에서 보는 방법으로 수정해야 했고… 예쁘게 만들기 어려웠다.

그러다가 추천받은 Tkinter. 관련해서 조금 더 찾아보다가 CustomTkinte 을 발견하게 되었고 검은색 화면에 반해서 바로 이걸로 개발하기로 했다.

그전 까지는 다 흰색 베이스에 회색 정도였는데 일단 검정! 이뻐!!!

customtkinter 설치

CustomTkinter : https://customtkinter.tomschimansky.com/

CustomTkinter
pip install customtkinter

pip install CTkMessagebox
pip install tkinterDnD2

pip install pillow          #pillow

CTkMessagebox 는 경고 메세지 등 창을 띄울 수 있게 해준다.


구조

main.py

import customtkinter
from tkinterdnd2 import TkinterDnD
from gui import GUI


class Tk(customtkinter.CTk, TkinterDnD.DnDWrapper):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.TkdndVersion = TkinterDnD._require(self)


def main():
    # root = customtkinter.CTk()    # 기존 customtkinter 윈도우 생성 를 TK()로 변경
    root = Tk()
    app = GUI(root)                 # GUI 클래스 인스턴스화
    app.run()                       # 앱 실행


if __name__ == "__main__":
    main()

기본 메인 구조는 이렇게 잡고

gui.py의 기본 첫 부분은

class GUI:
    def __init__(self, root):
        customtkinter.set_appearance_mode("dark")

        self.root = root
        self.root.title("Handy - Samsung Template Management")
        self.root.geometry("800x600")
        self.root.iconbitmap(os.path.join(IMG_FOLDER, "icon.ico"))
        self.root.grid_columnconfigure(1, weight=1)
        self.root.grid_rowconfigure(0, weight=1)

        self.contents = None
        self.tab_buttons = None
        self.tab1_content = None
        self.tab2_content = None
        self.tab3_content = None
        self.tab4_content = None
        self.tab1_value = None
        self.tab1_css_ltr = None
        self.tab1_css_rtl = None
        self.tab1_js_ltr = None
        self.tab1_js_rtl = None
        self.tab2_value = None
        self.drop_list_frame = None
        self.tab3_value_model = None
        self.tab4_deri = None
        self.tab4_os = None

        self.setup_layout_frame()
        select_tab(self.contents, self.tab_buttons, 0)

        self.template_manager = TemplateManager()
        self.setup_tab1()
        self.upload_manager = UploadManager()
        self.setup_tab2()
        self.model_manager = ModelManager()
        self.setup_tab3()
        # self.new_manager = NewManager(self.update_history, self.update_userpath, self.update_recom)  뒤에서 선언
        self.setup_tab4()

각 탭 메뉴 별로 파일을 독립 시켜 만들어 주었다.


.spec 파일

# -*- mode: python ; coding: utf-8 -*-


VERSION = '0.0.1'

a = Analysis(['app\\main.py'],
    pathex=['D:\\Develop\\D_handy'],
    binaries=[
        (r'D:\Develop\D_handy\vHandy\Lib\site-packages\tkdnd', 'tkdnd'),
        (r'D:\Develop\D_handy\vHandy\Lib\site-packages\tkinterdnd2', 'tkinterdnd2')

    ],
    datas=[
        (r'D:\Develop\D_handy\vHandy\Lib\site-packages\customtkinter', 'customtkinter/'),
        (r'img\*', 'img')
    ],
    hiddenimports=['CTkMessagebox'],
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=[],
    noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data)

exe = EXE(
    pyz,
    a.scripts,
    a.binaries,
    a.datas,
    [],
    name='Handy',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    upx_exclude=[],
    runtime_tmpdir=None,
    icon='img\\icon.ico',
    console=False,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
)

project Handy 개발 완료

customtkinter 써서 제작한 첫 프로그램이다.

중간에 지원 문서에 없는 걸 해야 할 땐 지원 문서에도 없는데 어떻게 하냐며 조금 짜증을 냈지만 확실히 pyqt 보다 편하게 작업할 수 있었다.

그리드 관련해서는 어차피 css에서 단련되어 금방 적용 가능했고(정말? 쿨럭)

  1. 엑셀 파일에서 해당 값을 찾아 실제 폴더 경로에서 원하는 값 가져오고
  2. 이미지 드래그 앤 드랍으로 실제 폴더에 업로드 하며 이때 동일 이미지 파일이 있으면 파일명을 파일명+현재 시간으로 변경해서 백업 후 진행 하도록 하였다.
  3. 엑셀에 원하는 시트를 찾아서 특정 값을 추가하며 실시간으로 수정 시 히스토리 엑셀을 따로 제작해서 하단에 보이도록 진행 했다. 물론 엑셀 값이 수정될 때 마다 백업용 엑셀을 만들었다.
  4. 동시 3개의 엑셀에 값을 추가하고 진행 상태는 체크로 진행 결과는 히스토리로 관리했다. 물론 각 버튼에서 파일을 바로 열어 수정되었는지 볼 수 있게 진행 했다.

사실 파이썬으로 주로 웹을 만들었었고 통계 프로젝트랑 크롤링 프로젝트, 최근 AI 프로젝트 까지 진행한적 있지만 응용프로그램은 유지 보수만 주로 했고 샘플이 아닌 실제 쓰는 프로그램을 제대로 제작할 기회가 없었는데 이번에 좋은 기회가 되었다.


최근 했던 다른 프로젝트 : [python/development] project Luna 설치 및 1차 개발 완료