2022년 12월 16일 금요일

파이썬 기반 멀티플랫폼 GUI 개발 라이브러리 wxPython 소개 및 사용하기

이 글은 유명한 파이썬 기반 크로스 플랫폼 GUI(Graphic User Interface) 개발 라이브러리 wxPython인 소개 및 사용방법을 간단히 설명한다.


소개
wxPython은 파이썬 프로그래밍용 크로스 플랫폼 GUI 라이브러리로, 동일한 코드로 윈도우, 맥북, 리눅스 등 다양한 플랫폼에 개발 코드와 디자인된 GUI를 그대로 재사용할 수 있다. wxPython은 Tkinter, Qt와 같은 GUI 디자인 API를 제공하지만, 사용방법이 쉽고, 편리한 레이아웃 기능등을 제공한다. 

wxPython은 Robin Dunn가 1995년 당시 개발되고 있던 wxWidgets 툴킷을 파이썬으로 랩핑하고, 편리하게 사용할 수 있도로 개선한 것이 개발의 시작이다. 참고로, wxWidgets은 에든버러 대학의 Julian Smart박사가 1992년 wxWindows란 이름으로 시작된 C++기반 GUI 오픈소스 프로젝트이다. 

wxWindows 로고와 Julian Smart 박사(참고)

wxPython은 2010년 피닉스 프로젝트가 시작되어, 파이썬 3과 호환되도록 하였고, 속도와 호환성을 개선했다. Robin Dunn은 2002년 프로그래머 초이스 어워드를 수상했으며, 2022년 6월 wxPython 4.x이 개발되고 있다. 
소프트웨어 엔지니어 Robin Dunn(참고)

시작
가장 단순한 예제는 다음과 같다.
import wx

app = wx.App()

frame = wx.Frame(None, title='Simple application')
frame.Show()

app.MainLoop()


여기서, 프레임위젯은 타이틀바, 경계, 위젯 컨테이너를 포함하는 윈도우이다. 
프레임 생성 옵션은 다음과 같이 추가할 수 있다.
wx.Frame(wx.Window parent, int id=-1, string title='', wx.Point pos=wx.DefaultPosition, size=(300, 200), style=wx.DEFAULT_FRAME_STYLE, string name="frame")

다음과 같이 툴바를 추가할 수 있다.
import wx

class Example(wx.Frame):
    def __init__(self, *args, **kwargs):
        super(Example, self).__init__(*args, **kwargs)
        self.InitUI()

    def InitUI(self):
        vbox = wx.BoxSizer(wx.VERTICAL)

        toolbar1 = wx.ToolBar(self)
        toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('tnew.png'))
        toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('topen.png'))
        toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('tsave.png'))
        toolbar1.Realize()

        toolbar2 = wx.ToolBar(self)
        qtool = toolbar2.AddTool(wx.ID_EXIT, '', wx.Bitmap('texit.png'))
        toolbar2.Realize()

        vbox.Add(toolbar1, 0, wx.EXPAND)
        vbox.Add(toolbar2, 0, wx.EXPAND)

        self.Bind(wx.EVT_TOOL, self.OnQuit, qtool)

        self.SetSizer(vbox)

        self.SetSize((350, 250))
        self.SetTitle('Toolbars')
        self.Centre()

    def OnQuit(self, e):
        self.Close()

def main():
    app = wx.App()
    ex = Example(None)
    ex.Show()
    app.MainLoop()

if __name__ == '__main__':
    main()

Sizer 사용해 레이아웃 디자인하기
사이저를 이용하면 손쉽게 레이아웃을 디자인할 수 있다. 다양한 위젯을 행이나 열로 추가하여, 프레임크기에 따라 포함된 위젯들의 상대적 위치 크기를 자동으로 배치한다.

다음은 BoxSizer 예시이다.
box = wx.BoxSizer(integer orient)
box.Add(wx.Window window, integer proportion=0, integer flag = 0, integer border = 0)

여기서 orient 방향은 wx.VERTICAL, wx.HORIZONTAL이 된다. 파라메터에서 proportion은 정의된 방향에 상대적으로 변화되는 위젯의 화며 크기 비율이다. 만약, 3개 위젯이 0, 1, 2로 proportion 값이 설정되어 있다면, 0번 위젯은 크기가 변하지 않고, 2번 위젯은 1번 위젯에 비해 2배 크기로 변경된다. 

flag는 위젯의 행위를 설정한다. 만약, 위젯 사이 공간을 추가하고 싶다면, 다음과 같은 옵션을 주면 된다. 

wx.LEFT, wx.RIGHT, wx.BOTTOM, wx.TOP, wx.ALL

다음은 사이저를 사용한 프레임 윈도우 생성 예시이다. 
import wx

class Example(wx.Frame):
    def __init__(self, parent, title):
        super(Example, self).__init__(parent, title=title)

        self.InitUI()
        self.Centre()

    def InitUI(self):
        panel = wx.Panel(self)

        panel.SetBackgroundColour('#4f5049')
        vbox = wx.BoxSizer(wx.VERTICAL)

        midPan = wx.Panel(panel)
        midPan.SetBackgroundColour('#ededed')

        vbox.Add(midPan, wx.ID_ANY, wx.EXPAND | wx.ALL, 20)
        panel.SetSizer(vbox)

def main():
    app = wx.App()
    ex = Example(None, title='Border')
    ex.Show()
    app.MainLoop()

if __name__ == '__main__':
    main()

여기서, 다음과 같이, wx.ALL 사용하면, 모든 방향의 경계에 퍼버를 20픽셀로 정의하고, wx.EXPAND 로 모든 위젯에 버퍼를 할당하게 된다. 
        vbox.Add(midPan, wx.ID_ANY, wx.EXPAND | wx.ALL, 20)

마무리 
wxPython 을 간단히 소개하고, 사용 방법을 간단히 알아보았다. 오픈소스로 개발된 지 거의 30년이 되어가는 데도, 꾸준히 유지보수되고 있는 프로젝트이다. 이 프로젝트는 파이썬에서 GUI를 개발할 때 거의 필수적으로 사용되는 라이브러리 중 하니이다. 역사를 살펴보면, 개발자의 사회적 공헌이 얼마나 좋은 영향을 미치는지는 느낄 수 있다. 한국에도 이런 문화가 정착되었을 때, IT선진국이라 할 수 있지 않을까 싶다. 

레퍼런스

추신. 유타 브리검 영 대학
라이브러리 개발자가 졸업한 유타주의 브레임영 대학은 미국에서 가장 큰 종교대학이다. 학생 98% 이상이 몰몬교도이다. 학교는 다른 미국 대학교에 비해 그리 크지 않은 편이지만, 컴퓨터 공학 등 이공대 경쟁력이 높은 곳 중 하나이다. 유타 종교 대학 특징 상 졸업생들은 올바른 종교 사회인으로써 역할에 충실한 편이며, 이로 인해, 많은 기업들이 이 대학교 졸업생을 선호한다고 한다. 

댓글 없음:

댓글 쓰기