PYTHON/tkinter

tkinter - 메모장 (3) - 단축키

고양이달리 2025. 2. 6. 11:10
def create_menu(window, txt):

    menu = Menu(window)
    menu_file = Menu(menu, tearoff=0)
    # todo. 단축키 -> 완료
    # accelerator: 어떤 키를 바인딩할 것인지 표시하는 것. 
    # lambda를 사용하지 않고 command: make_newone(window) 같은 형식으로 바로 함수가 실행되기 때문에 lambda를 사용한다. 
    menu_file.add_command(label="새로 만들기", command=lambda: make_newone(), accelerator="Ctrl+N")
    menu_file.add_command(label="새 창", command=lambda: make_window(window), accelerator="Ctrl+Shift+N")
    menu_file.add_command(label="열기", command=lambda: open_file(window, txt), accelerator="Ctrl+O")
    menu_file.add_command(label="저장", command=lambda: save_file(current_file, txt), accelerator="Ctrl+S")
    menu_file.add_command(label="다른 이름으로 저장", command=lambda: save_as(txt), accelerator="Ctrl+Shift+S")
    menu_file.add_command(label="PDF로 저장", command=lambda:save_txt_as_pdf(txt.get('1.0', END)))
    menu_file.add_separator()
    menu_file.add_command(label="페이지 설정",command=lambda: page_setup)
    # menu_file.add_command(label="인쇄", command=print) #lambda가 있고 없고랑 무슨 차이?
    menu_file.add_command(label="인쇄", command=lambda:print_txt(txt.get('1.0', END)), accelerator="Ctrl+P")
    menu_file.add_separator()
    menu_file.add_command(label="끝내기", command=window.quit)
    menu.add_cascade(label="파일", menu = menu_file)

    menu_edit = Menu(menu, tearoff=0)
    menu_edit.add_command(label="실행 취소", command=undo, accelerator="Ctrl+Z")
    menu_edit.add_separator()
    menu_edit.add_command(label="잘라내기", command=cut, accelerator="Ctrl+X")
    menu_edit.add_command(label="복사", command=lambda: copy(window, txt), accelerator="Ctrl+C")
    menu_edit.add_command(label="붙여넣기", command=paste, accelerator="Ctrl+V")
    menu_edit.add_command(label="삭제", command=delete, accelerator="Ctrl+D")
    menu_edit.add_separator()
    menu_edit.add_command(label="구글에서 검색하기", command=search_with_google, accelerator="Ctrl+F+G")
    menu_edit.add_command(label="찾기", command=find, accelerator="Ctrl+F")
    menu_edit.add_command(label="다음 찾기", command=find_next, accelerator="F3")
    menu_edit.add_command(label="이전 찾기", command=find_previous, accelerator="Shift+F3")
    menu_edit.add_command(label="바꾸기", command=replace, accelerator="Ctrl+H")
    menu_edit.add_command(label="이동", command=goto, accelerator="Ctrl+G")
    menu_edit.add_separator()
    menu_edit.add_command(label="모두 선택", command=lambda: select_all(txt), accelerator="Ctrl+A")
    menu_edit.add_command(label="시간/날짜", command=time_date, accelerator="F5")
    menu.add_cascade(label="편집", menu=menu_edit)

    menu_format = Menu(menu, tearoff=0)
    menu_format.add_command(label="자동 줄바꿈", command=word_wrap)
    menu_format.add_command(label="글꼴", command=font)
    menu.add_cascade(label="서식", menu=menu_format)

    menu_view = Menu(menu, tearoff=0)
    menu_view.add_checkbutton(label="확대하기/축소하기", command=zoom)
    menu_view.add_checkbutton(label="상태표시줄", command=status_bar)
    menu.add_cascade(label="보기", menu=menu_view)

    menu_help = Menu(menu, tearoff=0)
    menu_help.add_command(label="도움말 보기", command=view_help)
    menu_help.add_command(label="피드백 보내기", command=feedback)
    menu_help.add_separator()
    menu_help.add_command(label="메모장 정보", command=about_notepad)
    menu.add_cascade(label="도움말", menu=menu_help)

    window.config(menu = menu)
    
 def main():
    current_file = None

    window = Tk()
    window.title("제목 없음 - Windows 메모장")
    window.geometry("640x640+200+200")
    window.resizable(True, True)

    # 단축키 바인딩
    # bind: 객체에 이벤트 연결
    # lambda: 가 아닌 lambda e: 로 작성하는 이유? 람다 함수가 인자를 받을 수 있도록 수정함
    # tkinter는 이벤트가 발생할 때 이벤트 객체를 자동으로 전달함
    # labmda arguments: expression -> arguments: 함수가 받을 인자, expression: 반환 값
    # lambda: 인자를 받지 않음. 하지만 tkinter는 이벤트 객체를 전달하려고 하기 때문에 오류가 발생할 수밖에 없는 구조
    # lambda event: event라는 인자를 받음. tkinter가 이벤트 객체를 전달해도 오류가 발생하지 않음
    window.bind("<Control-n>", lambda e: make_newone())
    window.bind("<Control-Shift-n>", lambda e: make_window())
    window.bind("<Control-o>", lambda e: open_file())
    window.bind("<Control-s>", lambda e: save_file())
    window.bind("<Control-Shift-s>", lambda e: save_as())
    window.bind("<Control-p>", lambda e: print_txt())
    window.bind("<Control-q>", lambda e: window.quit())
    window.bind("<Control-z>", lambda e: undo())
    window.bind("<Control-x>", lambda e: cut())
    window.bind("<Control-c>", lambda e: copy())
    window.bind("<Control-v>", lambda e: paste())
    window.bind("<Control-d>", lambda e: delete())
    # todo. 찾기 안됨
    window.bind("<Control-f>", lambda e: find())
    window.bind("<F3>", lambda e: find_next())
    window.bind("<Shift-F3>", lambda e: find_previous())
    window.bind("<Control-h>", lambda e: replace())
    window.bind("<Control-g>", lambda e: goto())
    window.bind("<Control-a>", lambda e: select_all(txt))
    window.bind("<F5>", lambda e: time_date())

    scrollbar = Scrollbar(window)
    txt = Text(window, yscrollcommand=scrollbar.set)
    scrollbar.config(command=txt.yview)
    scrollbar.pack(side = "right", fill="y")
    # 다른 영역을 선택하면 클릭된 것 해제
    # <Button-1>은 왼쪽 마우스 버튼 클릭 이벤트를 뜻한다. 
    # <Button-2>은 중간 마우스 버튼 클릭 이벤트를 뜻한다. 
    # <Button-3>은 오른쪽 마우스 버튼 클릭 이벤트를 뜻한다. 
    # <Button-4>은 마우스 휠을 올리는 이벤트를 뜻한다.
    # <Button-5>은 마우스 휠을 내리는 이벤트를 뜻한다.
    # <ButtonPress>은 마우스 버튼 아무거나 클릭하는 이벤트를 뜻한다.
    txt.bind("<Button-1>", lambda e: txt.tag_remove("start", "1.0", "end"))
    txt.pack(fill="both", expand=True)

    create_menu(window, txt)

    window.mainloop()