Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

파이썬 Tkinter로 나만의 메모장 만들기 – GUI 텍스트 에디터 개발 완벽 가이드

Tkinter는 파이썬에 기본으로 포함된 GUI 라이브러리로, 이를 활용하면 다양한 데스크톱 애플리케이션을 손쉽게 만들 수 있습니다. 이번 글에서는 Tkinter를 이용해 윈도우 메모장과 같은 텍스트 편집기를 직접 개발해 보겠습니다. 완성된 메모장은 새 파일 만들기, 기존 파일 열기, 저장하기는 물론 잘라내기, 복사, 붙여넣기까지 실제 메모장에서 기대할 수 있는 핵심 기능을 모두 갖추게 됩니다.

개발 전 준비 사항

  • 파이썬(Python) 설치
  • Tkinter 설치

참고: Tkinter는 파이썬 3.x 버전부터 표준 라이브러리로 함께 배포되므로, 별도의 설치 과정 없이 바로 import해서 사용할 수 있습니다.

메뉴 항목 추가하기

우리가 만들 메모장은 네 개의 상위 메뉴를 가집니다. 바로 File(파일), Edit(편집), Commands(명령), Help(도움말)입니다.

File 메뉴에는 네 개의 하위 항목인 New(새로 만들기), Open(열기), Save(저장), Exit(종료)가 들어갑니다.

파이썬 Tkinter로 나만의 메모장 만들기 – GUI 텍스트 에디터 개발 완벽 가이드

Edit 메뉴에는 세 개의 하위 항목인 Cut(잘라내기), Copy(복사), Paste(붙여넣기)가 위치합니다.

파이썬 Tkinter로 나만의 메모장 만들기 – GUI 텍스트 에디터 개발 완벽 가이드

Commands 메뉴에는 About Commands(명령 안내) 한 개의 하위 항목을 추가합니다.

파이썬 Tkinter로 나만의 메모장 만들기 – GUI 텍스트 에디터 개발 완벽 가이드

마지막으로 Help 메뉴에는 About Notepad(메모장 정보) 항목 하나를 넣습니다.

파이썬 Tkinter로 나만의 메모장 만들기 – GUI 텍스트 에디터 개발 완벽 가이드

이처럼 다양한 메뉴와 하위 항목은 아래 코드를 통해 구현할 수 있습니다.

# 새 파일 열기
    self.__thisFileMenu.add_command(label="New",
    command=self.__newFile)
    # 이미 존재하는 파일 열기
    self.__thisFileMenu.add_command(label="Open",
    command=self.__openFile)
    # 현재 파일 저장
    self.__thisFileMenu.add_command(label="Save",
    command=self.__saveFile)
    # 대화상자에 구분선 추가
    self.__thisFileMenu.add_separator()
    self.__thisFileMenu.add_command(label="Exit",
    command=self.__quitApplication)
    self.__thisMenuBar.add_cascade(label="File", menu=self.__thisFileMenu)
    # 잘라내기 기능
    self.__thisEditMenu.add_command(label="Cut",
    command=self.__cut)
    # 복사 기능
    self.__thisEditMenu.add_command(label="Copy",
    command=self.__copy)
    # 붙여넣기 기능
    self.__thisEditMenu.add_command(label="Paste",
    command=self.__paste)
    # 편집 메뉴 등록
    self.__thisMenuBar.add_cascade(label="Edit", menu=self.__thisEditMenu)
    # 메모장 설명 표시 기능
    self.__thisHelpMenu.add_command(label="About Notepad",
    command=self.__showAbout)
    self.__thisCommandMenu.add_command(label = "About Commands", command=self.__showCommand)
    self.__thisMenuBar.add_cascade(label="Commands", menu=self.__thisCommandMenu)
    self.__thisMenuBar.add_cascade(label="Help", menu=self.__thisHelpMenu)

각 메뉴 항목에 기능 연결하기

메뉴 구조가 준비되었다면, 이제 각 메뉴 항목이 실제로 동작하도록 기능을 연결해야 합니다. 이번 예제에서 구현할 기능 목록은 다음과 같습니다. 물론 여러분의 필요에 따라 더 많은 기능을 자유롭게 추가할 수 있습니다.

  • 파일 열기
  • 새 파일 만들기
  • 파일 저장
  • 애플리케이션 종료
  • 정보 표시(About)
  • 명령 안내 표시
  • 잘라내기
  • 복사
  • 붙여넣기

위 기능들을 구현하는 코드는 아래와 같습니다.

def __quitApplication(self):
    self.__root.destroy()
    # exit()
def __showAbout(self):
    showinfo("About Notepad","Simple text editor like notepad using Python")
def __showCommand(self):
    showinfo("Notepad", "Just Another TextPad \n Copyright \n with BSD license you can use it'")
def __openFile(self):
    self.__file = askopenfilename(defaultextension=".txt", filetypes=[("All Files","*.*"),("Text Documents","*.txt")])
    if self.__file == "":
        # 열 파일이 없음
        self.__file = None
    else:
    # 파일 열기 시도
    # 창 제목 설정
    self.__root.title(os.path.basename(self.__file) + " - Notepad")
    self.__thisTextArea.delete(1.0,END)
    file = open(self.__file,"r")
    self.__thisTextArea.insert(1.0,file.read())
    file.close()
def __newFile(self):
    self.__root.title("Untitled Notepad")
    self.__file = None
    self.__thisTextArea.delete(1.0,END)
def __saveFile(self):
    if self.__file == None:
        # 새 이름으로 저장
    self.__file = asksaveasfilename(initialfile='Untitled.txt', defaultextension=".txt", filetypes=[("All Files","*.*"), ("Text Documents","*.txt")])
    if self.__file == "":
        self.__file = None
    else:
        # 파일 저장 시도
        file = open(self.__file,"w")
        file.write(self.__thisTextArea.get(1.0,END))
        file.close()
        # 창 제목 변경
        self.__root.title(os.path.basename(self.__file) + " - Notepad")
    else:
        file = open(self.__file,"w")
        file.write(self.__thisTextArea.get(1.0,END))
        file.close()
    def __cut(self):
        self.__thisTextArea.event_generate("<<Cut>>")
    def __copy(self):
        self.__thisTextArea.event_generate("<<Copy>>")
    def __paste(self):
        self.__thisTextArea.event_generate("<<Paste>>")

필요한 패키지 임포트, 메뉴 항목 추가, 그리고 각 기능의 구현까지 마쳤습니다. 이제 Tkinter 라이브러리를 활용해 만든 메모장 스타일 텍스트 편집기의 전체 모습을 확인할 차례입니다.

전체 소스 코드

아래는 지금까지 설명한 내용을 모두 담은 완전한 프로그램 코드입니다.

# os 라이브러리 임포트
import os
# tkinter의 모든 요소 임포트
from tkinter import *
# 메시지 위 공간 확보용
from tkinter.messagebox import *
# 필요할 때 대화상자 호출용
from tkinter.filedialog import *
class Notepad:
    # 루트 위젯 설정
    __root = Tk()
    __thisWidth = 500
    __thisHeight = 700
    __thisTextArea = Text(__root)
    __thisMenuBar = Menu(__root)
    __thisFileMenu = Menu(__thisMenuBar, tearoff=0)
    __thisEditMenu = Menu(__thisMenuBar, tearoff=0)
    __thisHelpMenu = Menu(__thisMenuBar, tearoff=0)
    __thisCommandMenu = Menu(__thisMenuBar, tearoff=0)
    # 스크롤바 추가
    __thisScrollBar = Scrollbar(__thisTextArea)
    __file = None
    def __init__(self,**kwargs):
        # 아이콘
        try:
            self.__root.wm_iconbitmap("Notepad.ico")
        except:
            pass
    # 위에서 지정한 값으로 창 크기 설정 (기본값은 300x300)
    try:
        self.__thisWidth = kwargs['width']
        except KeyError:
            pass
    try:
        self.__thisHeight = kwargs['height']
        except KeyError:
            pass
        # 창 제목 텍스트
        self.__root.title("Untitled-Notepad")
        # 창을 화면 중앙에 배치
        screenWidth = self.__root.winfo_screenwidth()
        screenHeight = self.__root.winfo_screenheight()
        # 좌측 정렬 좌표 계산
        left = (screenWidth / 2) - (self.__thisWidth / 2)
        # 우측 정렬 좌표 계산
        top = (screenHeight / 2) - (self.__thisHeight /2)
        # 상하 위치 적용
        self.__root.geometry('%dx%d+%d+%d' % (self.__thisWidth, self.__thisHeight, left, top))
        # 텍스트 영역 자동 리사이즈 설정
        self.__root.grid_rowconfigure(0, weight=1)
        self.__root.grid_columnconfigure(0, weight=1)
        # 컨트롤(위젯) 추가
        self.__thisTextArea.grid(sticky = N + E + S + W)
        # 새 파일 열기
        self.__thisFileMenu.add_command(label="New",
        command=self.__newFile)
        # 기존 파일 열기
        self.__thisFileMenu.add_command(label="Open",
        command=self.__openFile)
        # 현재 파일 저장
        self.__thisFileMenu.add_command(label="Save",
        command=self.__saveFile)
        # 대화상자에 구분선 추가
        self.__thisFileMenu.add_separator()
        self.__thisFileMenu.add_command(label="Exit",
        command=self.__quitApplication)
        self.__thisMenuBar.add_cascade(label="File", menu=self.__thisFileMenu)
        # 잘라내기 기능
        self.__thisEditMenu.add_command(label="Cut",
        command=self.__cut)
        # 복사 기능
        self.__thisEditMenu.add_command(label="Copy",
        command=self.__copy)
        # 붙여넣기 기능
        self.__thisEditMenu.add_command(label="Paste",
        command=self.__paste)
        # 편집 메뉴 등록
        self.__thisMenuBar.add_cascade(label="Edit", menu=self.__thisEditMenu)
        # 메모장 설명 표시 기능
        self.__thisHelpMenu.add_command(label="About Notepad",
        command=self.__showAbout)
        self.__thisCommandMenu.add_command(label = "About Commands", command=self.__showCommand)
        self.__thisMenuBar.add_cascade(label="Commands", menu=self.__thisCommandMenu)
        self.__thisMenuBar.add_cascade(label="Help", menu=self.__thisHelpMenu)
        self.__root.config(menu=self.__thisMenuBar)
        self.__thisScrollBar.pack(side=RIGHT,fill=Y)
        # 스크롤바가 내용에 맞춰 자동 조절됨
        self.__thisScrollBar.config(command=self.__thisTextArea.yview)
        self.__thisTextArea.config(yscrollcommand=self.__thisScrollBar.set)
    def __quitApplication(self):
        self.__root.destroy()
        # exit()
    def __showAbout(self):
        showinfo("About Notepad","Simple text editor like notepad using Python")
    def __showCommand(self):
        showinfo("Notepad", "Just Another TextPad \n Copyright \n with BSD license you can use it'")
    def __openFile(self):
        self.__file = askopenfilename(defaultextension=".txt", filetypes=[("All Files","*.*"),("Text Documents","*.txt")])
        if self.__file == "":
            # 열 파일이 없음
            self.__file = None
        else:
            # 파일 열기 시도
            # 창 제목 설정
            self.__root.title(os.path.basename(self.__file) + " - Notepad")
            self.__thisTextArea.delete(1.0,END)
            file = open(self.__file,"r")
            self.__thisTextArea.insert(1.0,file.read())
            file.close()
    def __newFile(self):
        self.__root.title("Untitled Notepad")
        self.__file = None
        self.__thisTextArea.delete(1.0,END)
    def __saveFile(self):
        if self.__file == None:
            # 새 이름으로 저장
            self.__file = asksaveasfilename(initialfile='Untitled.txt', defaultextension=".txt", filetypes=[("All Files","*.*"), ("Text Documents","*.txt")])
        if self.__file == "":
            self.__file = None
        else:
            # 파일 저장 시도
            file = open(self.__file,"w")
            file.write(self.__thisTextArea.get(1.0,END))
            file.close()
            # 창 제목 변경
            self.__root.title(os.path.basename(self.__file) + " - Notepad")
        else:
            file = open(self.__file,"w")
            file.write(self.__thisTextArea.get(1.0,END))
            file.close()
    def __cut(self):
        self.__thisTextArea.event_generate("<<Cut>>")
    def __copy(self):
        self.__thisTextArea.event_generate("<<Copy>>")
    def __paste(self):
        self.__thisTextArea.event_generate("<<Paste>>")
    def run(self):
        # 메인 애플리케이션 실행
        self.__root.mainloop()
# 메인 애플리케이션 실행
notepad = Notepad(width=600,height=400)
notepad.run()

실행 결과 확인하기

위 프로그램을 실행하면 아래와 같은 메모장 형태의 텍스트 편집기 창이 화면에 나타납니다.

파이썬 Tkinter로 나만의 메모장 만들기 – GUI 텍스트 에디터 개발 완벽 가이드

완성된 메모장에서는 텍스트를 자유롭게 입력하고 저장할 수 있으며, 저장해 둔 파일이나 다른 텍스트 파일을 언제든 다시 불러올 수 있습니다. 또한 열려 있는 문서의 내용을 대상으로 잘라내기, 복사, 붙여넣기 작업도 가능합니다. 직접 만든 이 메모장의 모든 메뉴 항목을 지금 바로 활용해 보세요.