본문 바로가기
Python

[Python] wxPython 맛보기

by 달나라외계인 2023. 12. 14.

  wxPython은 wxWidgets의 Python 버전입니다. 제가 Python을 잘 다루지는 않지만 C++은 메인언어로 사용중에 있는데요. 요즘 제가 크로스 플랫폼에 관심이 많아져서 c++에서 wxWidgets을 사용중에 있습니다. 사용법이 MFC와 유사하여 MFC에 익숙하신 분들은 쉽게 익힐 수 있습니다. 애시당초 MFC 대체 라이브러리를 표방하고 나왔고요. Python도 연장선으로서 GUI를 wxPython을 사용하게 되었습니다.

 

  크로스 플랫폼으로 나왔지만 자체 렌더러를 사용하는 다른 크로스 플랫폼과 달리 백엔드로 각 OS의 GUI 라이브러리나 프레임워크를 사용합니다. 윈도우에서는 win32 api의 윈도우 Handle을 이용하여 구현되어 있습니다. 나온지 좀 오래된 라이브러리라서 그런지 좀 오래된 느낌이 나는 라이브러리 입니다만 오히려 익숙한 부분이 있어서 사용하게 되었습니다. 아래는 wxWidgets과 wxPython 관련 사이트입니다. 관심이 있으시다면 한번쯤 들어가 보시는 걸 추천드립니다.

 

  장점이라면 qt 등보다는 라이선스에 좀 더 자유롭습니다. (wxWindows Licence)

 

https://www.wxwidgets.org/

 

wxWidgets: Cross-Platform GUI Library

wxWidgets is a C++ library that lets developers create applications for Windows, macOS, Linux and other platforms with a single code base. It has popular language bindings for Python, Ruby, Lua, Perl and several other languages, and unlike other cross-plat

www.wxwidgets.org

https://wxpython.org/index.html

 

Welcome to wxPython!

All about wxPython, the cross-platform GUI toolkit for the Python language

wxpython.org

  wxPython은 다음과 같이 pip을 이용하여 간단하게 설치하실 수 있습니다.

pip install wxpython

 

  오늘은 이글은 wxPython을 이용한 GUI 구성의 방법 소개가 목적입니다.

  이를 위해 예제를 중심으로 해서 간단하게 윈도우를 만들고, 텍스트 박스와 버튼을 배치한 후 버턴을 누르면 텍스트 박스의 내용을 메시지박스로 띄우는 프로그램을 만들어 보겠습니다. 이를 통하여 이벤트 처리 및 화면 배치를 어떻게 해야 하는지 대충 감을 잡을 수 있으시리라 생각합니다.

 

  기본 골격을 한번 만들어 보겠습니다.

  일단 모든 프로젝트가 그렇듯 라이브러리를 사용하기 전에 import를 먼저 진행합니다. 그 후 wxPython을 이용하여 GUI를 구성하시면 먼저 wx.App을 할당하셔야 합니다. wxPython으로 이루어진 App을 관리해 주는 메인 프레임입니다.

import wx

app = wx.App()

 

  그 이후 변수 window를 선언합니다. 변수 window 로 할당한 사용 클래스 MainWindow 는 밑에서 다시 정의하겠습니다. 아직 MainWindow 클래스를 정의하지 않았지만 윈도우 객체 입니다. Show 함수를 통해 윈도우 객체를  화면에 표시한 후 wx.App의 MainLoop 함수를 호출하면 main GUI 이벤트 루프가 동작합니다. 그 이후로 이벤트 루프 함수는 메인 윈도우가 닫히기 전까지는 끝나지 않을 겁니다.

window = MainWindow()
window.Show()

app.MainLoop()

 

  이제 MainWindow 클래스를 한번 정의해 보겠습니다. wx.Frame을 상속받아서 만듭니다.

  wx.Frame 은 이동과 사이즈 조절이 가능한 윈도우 입니다.

  부모 윈도우는 없으며, 타이틀이 'TEST' 라는 이름을 가지고 500 x 200 크기를 갖는 윈도우입니다.

class MainWindow(wx.Frame):
  def __init__(self):
    super().__init__(parent=None, title='TEST', size=wx.Size(500, 200))

  이것만으로 일단 빈 윈도우는 만들어 졌습니다. 이제 처음에 얘기한 것처럼 텍스트 박스와 버튼을 추가해 보겠습니다.

 

  __init__ 함수 안에서 마저 화면을 구성합니다. 먼저 BoxSizer 라는 것을 생성합니다. 이것은 실제 화면상에 보이는 물건이 아니라 화면배치하는 Layout을 위한 도구입니다. 밑에 코드는 컴포넌트를 추가할 때 세로 방향으로 구성하겠으며, 이것을 MainWindow의 기본 Layout으로 지정하겠다는 의미입니다.

 

base_sizer = wx.BoxSizer(orient=wx.VERTICAL)
self.SetSizer(base_sizer)

  이제 base_sizer에 텍스트박스와 버튼을 추가해 보겠습니다.

self.text_box = wx.TextCtrl(self, value='TEST')
button_sizer = wx.BoxSizer(orient=wx.HORIZONTAL)

base_sizer.Add(self.text_box, proportion=0, flag=wx.ALL|wx.EXPAND)
base_sizer.Add(button_sizer, proportion=1, flag=wx.ALL|wx.EXPAND)

  box_sizer의 Add 함수를 통해 sizer에 컴포넌트를 추가할 수 있습니다. 텍스트 박스와 button_sizer라는 또 다른 BoxSizer를 만들고 이것을 base_sizer에 추가하였습니다. 이것과 같이 일반 컴포넌트 뿐만 아니라 또 다른 sizer 만들고 이를 추가할 수도 있습니다. 그렇게 되면 좀 더 다양한 Layout을 구성할 수도 있겠죠. 이 button_sizer는 가로방향 컴포넌트 배치를 하게 하였습니다. Add 함수에서 proportion은 비율을 뜻합니다. 0이면 비율 조절을 하지 않겠다는 것입니다. 텍스트박스는 세로 방향을 크기 조절을 하지 않고 그냥 원래 텍스트 박스 크기로 붙이겠다는 뜻입니다. proportion가 1 이상이면 1이상인 다른 컴포넌트들의 비를 가지고 box_sizer 내의 영역을 비율로 나눠서 배치합니다. flag의 wx.ALL|wx.EXPAND 는 확장가능한 방향으로 해당 컨포넌트의 크기를 확장시키겠다는 의미입니다.

 

  이제 button_sizer에 이제 버튼을 추가하며 proportion을 좀 더 이해하기 편하게 proportion 값을 좀 다르게 설정해 보겠습니다.

self.button1 = wx.Button(self, label='메시지박스 띄우기')
self.button2 = wx.Button(self, label='끝내기')
button_sizer.Add(self.button1, proportion=2, flag=wx.ALL|wx.EXPAND)
button_sizer.Add(self.button2, proportion=1, flag=wx.ALL|wx.EXPAND)

  2대 1의 비율로 버튼을 가로 배치하라고 했습니다. 현재까지 구성해본 화면을 실행하여  한번 보여드리겠습니다.

  아직 버튼은 이벤트와 연결하지 않았지만 화면 구성이 끝났습니다.

  이제 각 버튼을 눌렀을 때 이벤트를 만들어 보겠습니다.

self.button1.Bind(wx.EVT_BUTTON, self. OnButton1Click)
self.button2.Bind(wx.EVT_BUTTON, self. OnButton2Click)

def OnButton1Click(self, event):
	wx.MessageBox('텍스트:' + self.text_box.GetValue())

def OnButton2Click(self, event):
	self.Close()

 

  '메시지박스 띄우기' 버튼을 누르면 텍스트 박스에 있는 내용을 읽어서 화면을 띄우게 하였고, '끝내기' 버튼을 누르면 창을 닫게 하였습니다.

  간단하지만 wxPython (or wxWidgets) 에서의 화면 배치 및 GUI 이벤트 처리에 대하여 알아보았습니다. 기록용으로 써두고 있는 것이라 궁금한 부분이 있으시다면 댓글 주시면 좀 더 내용을 보강하거나 해서 저도 한번 정리좀 해보겠습니다. 감사합니다.

 

타이핑이 귀찮으신 분들을 위한 전체 소스를 제공합니다.

더보기
import wx

class MainWindow(wx.Frame):
  def __init__(self):
    super().__init__(parent=None, title='TEST', size=wx.Size(500, 200))
    base_sizer = wx.BoxSizer(orient=wx.VERTICAL)
    self.SetSizer(base_sizer)

    self.text_box = wx.TextCtrl(self, value='TEST')
    button_sizer = wx.BoxSizer(orient=wx.HORIZONTAL)

    base_sizer.Add(self.text_box, proportion=0, flag=wx.ALL|wx.EXPAND)
    base_sizer.Add(button_sizer, proportion=1, flag=wx.ALL|wx.EXPAND)

    self.button1 = wx.Button(self, label='메시지박스 띄우기')
    self.button2 = wx.Button(self, label='끝내기')
    button_sizer.Add(self.button1, proportion=2, flag=wx.ALL|wx.EXPAND)
    button_sizer.Add(self.button2, proportion=1, flag=wx.ALL|wx.EXPAND)

    self.button1.Bind(wx.EVT_BUTTON, self. OnButton1Click)
    self.button2.Bind(wx.EVT_BUTTON, self. OnButton2Click)

  def OnButton1Click(self, event):
    wx.MessageBox('텍스트:' + self.text_box.GetValue())

  def OnButton2Click(self, event):
    self.Close()

app = wx.App()
window = MainWindow()
window.Show()

app.MainLoop()

'Python' 카테고리의 다른 글

[Python] django (2/3) template 맛보기  (0) 2024.05.25
[Python] django (1/3) module 맛보기  (0) 2024.04.13
[Python] datetime  (2) 2024.02.06
[Python] Argument Parser  (0) 2024.02.02
[Python] Config Parser  (0) 2023.12.11