본문 바로가기
Python/Python tkinter

[Python tkinter] 1. tkinter 패키지로 윈도우 창 생성하기

by Rosmary 2022. 1. 9.
728x90
반응형

 

 

 

 

필자가 지금까지 python이나 Linux Bash로 진행한 프로젝트들을 보면, 하나같이 Command Line Interface - 명령어를 입력하는 방식으로 구동하는 - 형태의 프로그램 뿐이다. 따라서 필자가 혼자 쓰기 아까운 프로그램들을 주변 가족들에게 소개시켜주더라도, 옛 도스와 비슷한 방식으로 작동하는 필자의 프로그램을 스마트폰에 익숙해진 사람들이 쓰기에는 많은 무리가 있다.

 

이 때문에 필자가 기존에 진행했던 프로젝트 중 일부를 Window에 익숙한 대부분의 현대 사람들도 쉽게 사용할 수 있게 Graphic User Interface 방식으로 변경하는 작업을 다시 진행하려고 마음먹었던 것이 무려 1년하고도 반년 전이다. 이 당시 찾아본 결과 python의 tkinter 패키지와 PyQt5라는 패키지가 GUI 프로그램 생성에 가장 많이 사용된다는 것을 알게 되었다. 차근차근 변경 작업을 진행하기 위해 학습을 진행했으나... 여러 포스팅에서 하는 소리지만 여유 시간이 나지 않아 지속적으로 공부를 할 수 없어 별도로 포스팅을 작성하지 못했다. 하지만 작년 말에 취득하려했던 자격증도 최종 취득이 완료되었고, 새해도 시작되어 GUI 프로그래밍과 관련된 공부와 포스팅을 다시 진행하려한다. 

 

 

 

I. 왜 tkinter인가?

 

python에서 GUI 프로그래밍에 주로 사용하는 패키지는 tkinter와 PyQt5가 있다. tkinter는 간략하게 Window 창을 구성하는 경우 주로 사용하며 반대로 PyQt5는 섬세하게 Window 창을 구성해야 하는 때에 많이 사용한다. 

 

"어?? 그럼 PyQt5를 사용하면 더 멋진 GUI 프로그램을 만들 수 있을텐데, 왜 tkinter를 사용하려는 건가요?"

 

tkinter는 python에서 기본으로 제공하는 패키지다. 이 말인 즉슨, pip install 명령어를 통해 패키지를 새로 다운받을 필요가 없다는 말이다. 필자의 경우, 제작한 코드 파일을 실행 파일로 변환하는 작업을 진행한 뒤 필요한 사람들에게 배포하는데 해당 프로그램을 사용하는 PC에 python이 설치되어 있지 않다던가, 또는 python이 존재하더라도 외부 패키지가 없어 실행 파일이 제대로 돌지 않았던 경험이 많아 되도록이면 기본 패키지를 사용하여 코딩하려 하기 때문이다. 물론 외부 패키지를 사용하더라도 방법을 잘 찾아보면 실행 파일로 변환한 프로그램이라도 잘 동작할 수 있겠지만... 아직은 시간적인 여유가 없다.

 

또한 현재 필자가 업무적인 이유로 인해 GUI 프로그램 개발 프로젝트를 진행하고 있는데, 아무래도 고객사에 python이 설치되어 있는 곳이 많지 않기 때문에 기본 패키지로만 프로젝트를 진행해야 하는 상황도 tkinter를 먼저 학습하게 된 이유다. 따라서 언젠가는 필자가 PyQt5로 독학한 뒤 포스팅을 올리긴 하겠지만... 언제가 될 지는 모르겠다.

 

본격적으로 tkinter를 사용한 window GUI 프로그래밍에 대한 포스팅을 시작하려 한다. 

첫 주제는 창 생성하기.

 

 

 

II. Window 창 생성하기

1. Tk() 클래스로 창 생성

 

먼저, 테스트를 진행할 python 스크립트 파일(.py)을 생성하고, 파일 내에 tkinter 패키지 import를 진행하자.

이 tkinter 패키지 내에는 Tk()라는 이름을 가지는 class가 존재하는데, 이 클래스가 선언되는 순간 window 창이 화면에 생성된다. 

 

 

이제 이 파일을 cmd 창에서 실행해보자. 그럼 예상과 다르게 창이 나타나지 않고 프로그램이 종료되는 상황이 나타날 것이다. 너무나도 당연하게도, 윈도우 창을 생성하는데 관여하는 Tk()가 선언된지 얼마 되지 않아 프로그램이 종료되기 때문에 인지할 수 없을 정도로 아주 짧은 시간동안만 화면에 창이 생성되었다가 사라지기 때문이다.

 

따라서 프로그램이 종료되지 않도록 유지할 수 있는 코드를 작성해주면 된다. Tk() 클래스 내에는 mainloop()라는 매서드가 존재하는데, 위와 같이 생성된 창이 닫히지 않도록 유지해주는 역할을 하는 매서드라고 보면 된다. Tk() 클래스를 선언한 코드 아래에 mainloop() 매서드를 작성하고 다시 cmd로 실행해보자.

 

 

 

기본적인 Window 창 생성 코드는 이것이 끝이다. 그럼, 생성할 창의 크기 조정, 처음 팝업할 위치 등등을 설정할 수 있는 방법은 없을까? 당연히 있다.

 

 

 

2. Window 창 크기 및 초기 위치 조절: tkinter.Tk().geometry()

 

mainloop() 매서드 코드 위로 생성할 창의 크기를 지정할 코드를 작성해보려 한다. Tk() 클래스 내 매서드 중 geometry()라는 이름의 매서드가 있는데 창의 크기 및 첫 팝업 위치를 지정하는 역할을 한다(매서드 이름으로 어느 정도 유추가 가능하다).

 

geometry() 내 인자값은 String 타입인데, 인자의 형태가 매우 중요하다.

 

tkinter.Tk().geometry( "Str 인자값 입력" )

"{창의 가로축 Pixel크기}x{창의 세로축 Pixel크기}+{창의 가로축 초기 위치(Pixel)}+{창의 가로축 초기 위치(Pixel)}"

 

위의 포맷으로 아래와 같이 코드를 추가한 뒤 cmd로 실행하면 창의 크기가 변화한 것을 확인할 수 있다.

 

필자는 추후 변경 사항 발생 시 편의를 위해 변수로 인자값을 설정하는데, 인자값을 직접 입력해도 동일한 결과가 나타난다

 

참고로 위치 조정에 사용하는 플러스(+) 기호는 마이너스(-) 기호로도 대체할 수 있는데, 마이너스를 사용하는 경우 X축은 우측, Y축은 아래방향부터 지정한 pixel 만큼 떨어진 위치에 창이 생성된다.

 

 

 

3. Window 창 크기 조절 가능 여부 설정: tkinter.Tk().resizable()

 

Tk() 클래스를 통해 기본 생성된 창은 마우스로 창의 크기 조절이 가능하다. 하지만 GUI 프로그래밍으로 이런저런 창을 생성하다보면 창의 크기를 고정해놓아야 하는 경우가 발생하기도 한다. 이 때 사용하는 Tk() 클래스 매서드로 resizable()이 존재하며, 인자는 x축의 사이즈 조절 가능 여부 및 y축의 사이즈 조절 가능여부를 Boolean값으로 지정한다.

 

tkinter.Tk().resizable( X축 사이즈 조절 가능 여부, Y축 사이즈 조절 가능 여부 )

 

resizable 인자는 기본값으로 True, True를 가진다. 따라서 resizable에 대한 별도의 설정이 없다면 마우스로 창의 크기 조절이 가능하다. 

 

 

 

 

4. Window 창 Title 설정: tkinter.Tk().title()

 

Tk() 클래스로 생성한 창의 좌측 상단을 보면 창의 이름이 'tk'로 설정되어 있는 것을 볼 수 있다. 이 값을 바꾸는 매서드 역시 Tk() 클래스에 title() 이라는 이름으로 존재한다.

 

title() 매서드 인자는 String 타입을 사용하며, title에 사용할 이름을 지정해주면 된다.

 

 

 

 

5. window 창 Icon 설정: tkinter.Tk().iconphoto()

 

생성한 창의 Title 말고 왼쪽에 존재하는 기본 아이콘도 변경이 가능할까? 당연히 된다. Tk() 매서드의 iconphoto()를 사용하면 되며, 인자는 Icon으로 사용할 이미지를 tkinter.PhotoImage 객체로 변환하여 사용하면 된다.

 

* tkinter.PhotoImage는 추후 포스팅 예정이다.

 

먼저 창에 사용할 아이콘을 만들어보자. 거창한 것 만들지 말고 Google Chrome 아이콘을 복사해 그림판에 붙여넣고 파일을 저장하자. 필자는 python 파일과 동일한 경로에 icon1.png라는 파일명으로 저장했다.

 

다음으로 iconphoto 매서드를 사용하여 코드를 작성한다. iconphoto()는 인자로 default=False와 PhotoImage객체를 가지는데, default 값은 큰 의미가 없고, PhotoImage 객체는 icon으로 사용할 이미지를 지정하는 것이라 보면 된다.

 

tkinter.Tk().iconphoto(False, tkinter.PhotoImage(file='아이콘 이미지 파일 경로')

 

 

 

6. Window 창이 실행되는 컴퓨터의 모니터 크기 확인: winfo_screenwidth(), winfo_screenheight()

 

GUI 프로그래밍을 하다보면 화면의 정 가운데에 창을 위치시켜야하는 경우가 종종 있다. 로그인 화면이라던가... 그런데, 프로그램이 실행되는 화면의 크기, 즉 모니터 크기가 제각각이다보니, 코딩하면서 화면 가운데 위치하도록 만들어 놓은 코딩값들이 모니터 크기가 조금이라도 달라지면 무용지물이 되어 버린다. 

 

이 때문에 Tk() 매서드는 Window 창이 실행되는 화면의 모니터 크기를 반환하는 매서드를 가진다. winfo_screenwidth()와 winfo_screenheight()가 이 역할을 담당하며 해당 매서드들은 각각 모니터의 가로축과 세로축 Pixel 크기를 반환한다.

 

 

어떠한 크기의 window 창을 생성하더라도 모니터의 크기 값을 활용하여 창을 한 가운데에 배치하는 것이 가능해진다. 해당 코드는 아래에 예시로 올려놓으니 각자 분석해보도록 하자.

 

 

 

 

7. 생성한 Window 창의 종료: tkinter.Tk().quit(), tkinter.Tk().destroy(), tkinter.Tk().forget()

 

마지막으로 창의 종료와 관련된 매서드를 알아보자. 일반적인 창처럼 오른쪽 위의 X 버튼을 눌러 창을 닫을 수도 있지만, 이렇게 창을 닫는 경우, tkinter에서는 마치 Ctrl + C를 누른 것과 동일한 효과가 나타나게 된다. 다시 말하자면, 프로그램이 정상 종료된 것이 아니라 Keyboard Interrupt에 의해 강제 종료되는 것과 같다는 것이다.

 

추후 포스팅에서 배울 내용이지만 Button 하나를 생성해보자. 그리고 이 버튼을 클릭하면 "프로그램이 종료됩니다"라는 문구가 표시되도록 해보자.

 

 

먼저 Exit 버튼을 클릭했을 때의 결과다. 위의 결과 화면과 같이 CMD 창에 "프로그램이 종료됩니다"라는 문구가 출력되는 것이 보인다.

 

하지만 우측 상단의 X 버튼으로 창을 닫게 될 경우, "프로그램을 종료합니다"라는 문구가 출력되지 않는다. 별 것 아닌 것 같지만 굉장히 중요한데, 프로그램의 동작을 일일이 로그로 남겨 추후 개발 중 버그 발생 시 확인할 때, 프로그램이 진짜 이상이 있어서 Interrupt 종료가 되었는지, 아니면 사용자에 의해 종료가 되었는지 판단하기가 매우 어렵기 때문이다(이 부분은 추후 다른 포스팅에서 다루려 한다).

 

따라서 tkinter에서는 프로그램 종료 매서드나 함수를 별도로 만들어 동작하도록 하는 것이 기본인데, 이 때 사용하는 Tk() 매서드로는 quit()과 destroy()가 있다. 

 

quit() 매서드는 window의 mainloop 과정을 끝낸다는 의미다. 따라서, 해당 매서드가 실행되는 순간 생성한 window 창은 닫히게 된다. 생성한 button1의 command에 quit() 매서드를 추가해 확인해보자.

 

그렇다면 destroy()는 무슨 역할을 할까? quit()과 유사하게 mainloop를 종료하지만 종료하기 전에 매서드 이름과 같이 window에 생성한 모든 widget(버튼, 박스 등등)을 모두 삭제한다...라고 공식 문서에 나타나나 테스트를 진행해보니 사실상 quit()과 큰 차이가 있지는 않은 듯 하다. 

 

두 매서드 외에 forget()이라는 매서드도 존재한다. Tk() 객체인 자기 자신을 이 매서드 인자로 삼아 창을 삭제하는 것도 가능하다. 단, 앞의 두 매서드와 달리, 창 종료 후의 코드를 실행하지 않고 바로 프로그램을 종료해버린다는 것이 차이점이다.

 

* 오늘 포스팅에서 사용한 코드를 공유한다. 필요하신 분들은 다운받아 쓰시면 된다.

001_tkinter_creating_window.py
0.00MB


 

다음 포스팅에서는 창 내 Frame, 즉 구역 지정과 관련된 내용에 대해 포스팅해보려 한다.

 

 

 

Fin.

 

 

 

 

반응형

댓글