GUI with wxPython [KOR]
In [1]:
from IPython.display import Image
wx 모듈 input
In [2]:
import wx
import wx.xrc
기본 창띄우기
In [3]:
app = wx.App(False)
frame = wx.Frame(None, wx.ID_ANY, "Hello World")    # Frame 클래스. 컨테이너 역할
frame.Show(True)
app.MainLoop()    # # 무한루프에 빠뜨린다
In [4]:
# 출력되는 창
Image("gui1.png")
Out[4]:
wx.Frame 상속받고 창을 만들기
In [5]:
import wx
class Ex(wx.Frame):    # wx.Frame 상속
    def __init__(self, parent, title):
        super(Ex, self).__init__(parent, title=title, size=(400,300))
        
        # TextBox 추가
        # self.txtA = wx.TextCtrl(self)    # 한 줄 입력 위젯(컴포넌트, 컨트롤)
        # self.txtA = wx.TextCtrl(self, style = wx.TE_MULTILINE)    # 여러 줄 입력 위젯
        
        # 윈도우 하단에 상태 표시줄 표시
        self.CreateStatusBar()
        self.SetStatusText('YoungJin Kang')
        
        # 메뉴 작성 - 메뉴바에 메뉴를 등록하고 메뉴에 메뉴 아이템을 등록
        menuBar = wx.MenuBar()    # 메뉴바 
        
        mnuFile = wx.Menu()    # 주메뉴
        
        mnuNew = mnuFile.Append(wx.ID_NEW, 'New', '새글')    # 메뉴 아이템 (부메뉴)
        mnuOpen = mnuFile.Append(wx.ID_OPEN, '&Open \tCtrl+O', '열기')    # \t뒤에는 단축키 추가
        mnuFile.AppendSeparator()    # 메뉴에 구분선 추가
        mnuExit = mnuFile.Append(wx.ID_EXIT, 'Exit', '닫기') 
        
        menuBar.Append(mnuFile, '&File')    # &는 엑세스 키설정(여기서는 alt+F 를 누르면 메뉴바가 눌린다)
        
        self.SetMenuBar(menuBar)    # 메뉴바를 Frame에 등록
        
        # 라벨과 텍스트 처리 관련 위젯
        panel = wx.Panel(self)
        wx.StaticText(panel, label = 'i d : ', pos = (5, 5))
        wx.StaticText(panel, label = 'pwd : ', pos = (5, 40))
        self.txtA = wx.TextCtrl(panel, pos = (40, 5))
        self.txtB = wx.TextCtrl(panel, pos = (40, 40))
        
        # 메뉴에 이벤트를 장착
        self.Bind(wx.EVT_MENU, self.OnEvent1, mnuNew)    # mnuNew를 클릭하면 OnEvent1 이벤트 핸들러를 호출
        self.Bind(wx.EVT_MENU, self.OnEvent2, mnuOpen)
        self.Bind(wx.EVT_MENU, self.OnEvent3, mnuExit)
        
        # 버튼을 배치하고 이벤트 처리1
        btn1 = wx.Button(panel, label = '버튼1', pos = (10, 100))
        btn2 = wx.Button(panel, label = '버튼2', pos = (100, 100))
        btn3 = wx.Button(panel, label = '종 료', pos = (190, 100))
        
        # 버튼에 이벤트를 장착하고 버튼 이벤트 처리 방법1
        btn1.Bind(wx.EVT_BUTTON, self.OnBtn1, btn1)    # 각각의 버튼에 대한 핸들러 메소드 작성
        btn2.Bind(wx.EVT_BUTTON, self.OnBtn2, btn2)
        btn3.Bind(wx.EVT_BUTTON, self.OnBtn3, btn3)
        
        # 버튼을 배치하고 이벤트 처리2
        btn4 = wx.Button(panel, label = '버튼3', pos = (10, 150))
        btn5 = wx.Button(panel, label = '버튼4', pos = (100, 150))
        btn6 = wx.Button(panel, label = '종 료', pos = (190, 150))
        
        # 버튼에 이벤트를 장착하고 버튼 이벤트 처리 방법2
        btn4.id = 1; btn5.id = 2; btn6.id = 3;    # 각 버튼을 구분하기 위해 id를 준다
        btn4.Bind(wx.EVT_BUTTON, self.OnBtnProcess)    # 여러 버튼에 대한 핸들러 메소드 한 개 작성
        btn5.Bind(wx.EVT_BUTTON, self.OnBtnProcess)
        btn6.Bind(wx.EVT_BUTTON, self.OnBtnProcess)        
        
        # 창 실행
        self.Center()
        self.Show()
    
    # 이벤트 핸들러 메소드
    def OnEvent1(self, event):    # 이벤트 핸들러 메소드는 event 매개변수를 준다
        self.txtA.SetLabelText('새문서 메뉴 선택')
        self.txtB.SetLabelText('')
        
    def OnEvent2(self, event):    
        self.txtB.SetLabelText('열기 메뉴 선택')
        self.txtA.SetLabelText('')
    
    def OnEvent3(self, event):    
        self.Close(True)    # 실행 중인 Frame 닫기
        
    def OnBtn1(self, event):
        self.txtA.SetLabelText('버튼1 선택')
    
    def OnBtn2(self, event):
        self.txtA.SetLabelText('버튼2 선택')
    
    def OnBtn3(self, event):
        self.Close()
    
    def OnBtnProcess(self, event):
        if event.GetEventObject().id == 1:
            self.txtB.SetLabelText('버튼3 선택')
        elif event.GetEventObject().id == 2:
            self.txtB.SetLabelText('버튼4 선택')
        else:
            self.Close()
# 실행 명령         
if __name__ == '__main__':
    app = wx.App()
    Ex(None, '윈도우연습')
    app.MainLoop()    # 무한루프에 빠뜨린다
In [6]:
# 출력 되는 창
with open('gui2.gif','rb') as file:
    display(Image(file.read()))
ListCtrl 위젯(표 형태로 자료 출력) 사용하기
In [7]:
import wx
fdatas = [
    ('홍길동', '서울', '2000'),
    ('김치국', '경기', '2005')
]
class MyFrame(wx.Frame):
    def __init__(self, parent, title):
        super(MyFrame, self).__init__(parent, title=title, size=(300,250))
        
        self.dataList = wx.ListCtrl(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LC_REPORT)
        self.dataList.InsertColumn(0, '이름', width = 100)
        self.dataList.InsertColumn(1, '출생지', width = 100)
        self.dataList.InsertColumn(2, '출생년도', width = 100)
        
        self.Center()
        
        tu = ('신기해', '제주', '2002')
        fdatas.append(tu)
        
        for f in fdatas:
            index = self.dataList.InsertItem(1000, f[0])
            self.dataList.SetItem(index, 1, f[1])
            self.dataList.SetItem(index, 2, f[2])
            
# 실행 명령
  
if __name__ == '__main__':
    app = wx.App()
    MyFrame(None, 'ListCtrl 위젯').Show()
    app.MainLoop()    # 무한루프에 빠뜨린다
In [8]:
# 출력되는 창
Image("gui3.jpg")
Out[8]:
wxFormBuilder 로 제작하고 복사하기
1. 이름 나이 저장
In [9]:
import wx
class MyFrame1 ( wx.Frame ):
    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 400,300 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
        
        # self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
        self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_MENU ) )
        
        bSizer1 = wx.BoxSizer( wx.VERTICAL )
        
        self.m_panel1 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
        bSizer2 = wx.BoxSizer( wx.HORIZONTAL )
        
        self.m_staticText1 = wx.StaticText( self.m_panel1, wx.ID_ANY, u"이름 : ", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.m_staticText1.Wrap( -1 )
        bSizer2.Add( self.m_staticText1, 0, wx.ALL, 5 )
        
        self.txtName = wx.TextCtrl( self.m_panel1, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
        bSizer2.Add( self.txtName, 0, wx.ALL, 5 )
        
        
        self.m_panel1.SetSizer( bSizer2 )
        self.m_panel1.Layout()
        bSizer2.Fit( self.m_panel1 )
        bSizer1.Add( self.m_panel1, 0, wx.ALL|wx.EXPAND, 5 )
        
        self.m_panel2 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
        bSizer3 = wx.BoxSizer( wx.HORIZONTAL )
        
        self.m_staticText4 = wx.StaticText( self.m_panel2, wx.ID_ANY, u"나이 : ", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.m_staticText4.Wrap( -1 )
        bSizer3.Add( self.m_staticText4, 0, wx.ALL, 5 )
        
        self.txtAge = wx.TextCtrl( self.m_panel2, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
        bSizer3.Add( self.txtAge, 0, wx.ALL, 5 )
        
        self.m_button1 = wx.Button( self.m_panel2, wx.ID_ANY, u"확인", wx.DefaultPosition, wx.DefaultSize, 0 )
        bSizer3.Add( self.m_button1, 0, wx.ALL, 5 )
        
        
        self.m_panel2.SetSizer( bSizer3 )
        self.m_panel2.Layout()
        bSizer3.Fit( self.m_panel2 )
        bSizer1.Add( self.m_panel2, 0, wx.EXPAND |wx.ALL, 5 )
        
        self.m_panel3 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
        bSizer4 = wx.BoxSizer( wx.HORIZONTAL )
        self.staShow = wx.StaticText( self.m_panel3, wx.ID_ANY, u"결과보기", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.staShow.Wrap( -1 )
        bSizer4.Add( self.staShow, 0, wx.ALL, 5 )
            
        
        self.m_panel3.SetSizer( bSizer4 )
        self.m_panel3.Layout()
        bSizer4.Fit( self.m_panel3 )
        bSizer1.Add( self.m_panel3, 0, wx.EXPAND |wx.ALL, 5 )
        
        
        self.SetSizer( bSizer1 )
        self.Layout()
        
        self.Centre( wx.BOTH )
        
        # Connect Events
        self.m_button1.Bind( wx.EVT_BUTTON, self.ShowData )
    def __del__( self ):
        pass
    
    
    # Virtual event handlers, overide them in your derived class
    def ShowData( self, event ):    # 이부분만 직접 작성
        name = self.txtName.GetValue()
        age = self.txtAge.GetValue()
        self.staShow.SetLabelText(name + "님의 나이는 " + age)
# 실행 명령        
if __name__ == '__main__':
    app = wx.App()
    MyFrame1(None).Show()
    app.MainLoop()    # 무한루프에 빠뜨린다
In [10]:
# 출력되는 창
with open('gui4.gif','rb') as file:
    display(Image(file.read()))
Image("gui4_wx.png")
Out[10]:
2. 상품 저장
In [11]:
import wx
class MySangpum ( wx.Frame ):
    
    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 595,450 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
        
        # self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
        self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_MENU ) )
        
        bSizer1 = wx.BoxSizer( wx.VERTICAL )
        
        self.m_panel1 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
        bSizer2 = wx.BoxSizer( wx.HORIZONTAL )
        
        self.m_staticText1 = wx.StaticText( self.m_panel1, wx.ID_ANY, u"품명 : ", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.m_staticText1.Wrap( -1 )
        bSizer2.Add( self.m_staticText1, 0, wx.ALL, 5 )
        
        self.txtSang = wx.TextCtrl( self.m_panel1, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size( -1,-1 ), 0 )
        bSizer2.Add( self.txtSang, 0, wx.ALL, 5 )
        
        
        self.m_panel1.SetSizer( bSizer2 )
        self.m_panel1.Layout()
        bSizer2.Fit( self.m_panel1 )
        bSizer1.Add( self.m_panel1, 1, wx.EXPAND |wx.ALL, 5 )
        
        self.m_panel2 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
        bSizer3 = wx.BoxSizer( wx.HORIZONTAL )
        
        self.m_staticText2 = wx.StaticText( self.m_panel2, wx.ID_ANY, u"수량 : ", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.m_staticText2.Wrap( -1 )
        bSizer3.Add( self.m_staticText2, 0, wx.ALL, 5 )
        
        self.txtSu = wx.TextCtrl( self.m_panel2, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
        bSizer3.Add( self.txtSu, 0, wx.ALL, 5 )
        
        
        self.m_panel2.SetSizer( bSizer3 )
        self.m_panel2.Layout()
        bSizer3.Fit( self.m_panel2 )
        bSizer1.Add( self.m_panel2, 1, wx.EXPAND |wx.ALL, 5 )
        
        self.m_panel3 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
        bSizer5 = wx.BoxSizer( wx.HORIZONTAL )
        
        self.m_staticText3 = wx.StaticText( self.m_panel3, wx.ID_ANY, u"단가 : ", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.m_staticText3.Wrap( -1 )
        bSizer5.Add( self.m_staticText3, 0, wx.ALL, 5 )
        
        self.txtDan = wx.TextCtrl( self.m_panel3, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
        bSizer5.Add( self.txtDan, 0, wx.ALL, 5 )
        
        self.btnInsert = wx.Button( self.m_panel3, wx.ID_ANY, u"등록", wx.DefaultPosition, wx.DefaultSize, 0 )
        bSizer5.Add( self.btnInsert, 0, wx.ALL, 5 )
        
        
        self.m_panel3.SetSizer( bSizer5 )
        self.m_panel3.Layout()
        bSizer5.Fit( self.m_panel3 )
        bSizer1.Add( self.m_panel3, 1, wx.EXPAND |wx.ALL, 5 )
        
        self.m_panel4 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
        bSizer4 = wx.BoxSizer( wx.VERTICAL )
        
        self.lstView = wx.ListCtrl( self.m_panel4, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LC_REPORT )
        bSizer4.Add( self.lstView, 1, wx.ALL|wx.EXPAND, 5 )
        
        
        self.m_panel4.SetSizer( bSizer4 )
        self.m_panel4.Layout()
        bSizer4.Fit( self.m_panel4 )
        bSizer1.Add( self.m_panel4, 1, wx.EXPAND |wx.ALL, 5 )
        
        self.m_panel5 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
        bSizer6 = wx.BoxSizer( wx.VERTICAL )
        
        self.staShow = wx.StaticText( self.m_panel5, wx.ID_ANY, u"건수 : 0", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.staShow.Wrap( -1 )
        bSizer6.Add( self.staShow, 0, wx.ALL, 5 )
        
        
        self.m_panel5.SetSizer( bSizer6 )
        self.m_panel5.Layout()
        bSizer6.Fit( self.m_panel5 )
        bSizer1.Add( self.m_panel5, 1, wx.EXPAND |wx.ALL, 5 )
        
        # lstView에 제목 추가    # 직접 추가한 부분
        self.lstView.InsertColumn(0, "상품명", width = 170)
        self.lstView.InsertColumn(1, "수량", width = 100)
        self.lstView.InsertColumn(2, "단가", width = 100)
        
        
        self.SetSizer( bSizer1 )
        self.Layout()
        
        self.Centre( wx.BOTH )
        
        # Connect Events
        self.btnInsert.Bind( wx.EVT_BUTTON, self.InsertSangpum )
    
    def __del__( self ):
        pass
    
    
    # Virtual event handlers, overide them in your derived class
    def InsertSangpum( self, event ):    # 직접 추가한 부분
        sang = self.txtSang.GetValue()
        su = self.txtSu.GetValue()
        dan = self.txtDan.GetValue()
        
        i = self.lstView.InsertItem(10000, 0)    # 2147483647 까지 가능
        self.lstView.SetItem(i, 0, sang)
        self.lstView.SetItem(i, 1, su)
        self.lstView.SetItem(i, 2, dan)
        self. staShow.SetLabelText('건수 : ' + str(self.lstView.GetItemCount()))
        
        self.txtSang.SetValue('')
        self.txtSu.SetValue('')
        self.txtDan.SetValue('')
# 실행 명령        
if __name__ == '__main__':
    app = wx.App()
    MySangpum(None).Show()
    app.MainLoop()    # 무한루프에 빠뜨린다
In [12]:
# 출력되는 창
with open('gui5.gif','rb') as file:
    display(Image(file.read()))
Image("gui5_wx.png")
Out[12]:
3. 계산기 만들기
In [13]:
import wx
class MyCalc ( wx.Frame ):
    
    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"미니 계산기", pos = wx.DefaultPosition, size = wx.Size( 387,301 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
        
        # self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
        self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_MENU ) )
        
        bSizer1 = wx.BoxSizer( wx.VERTICAL )
        
        self.m_panel1 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
        bSizer2 = wx.BoxSizer( wx.HORIZONTAL )
        
        self.m_staticText1 = wx.StaticText( self.m_panel1, wx.ID_ANY, u"숫자1 : ", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.m_staticText1.Wrap( -1 )
        bSizer2.Add( self.m_staticText1, 0, wx.ALL, 5 )
        
        self.txtNum1 = wx.TextCtrl( self.m_panel1, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
        bSizer2.Add( self.txtNum1, 0, wx.ALL, 5 )
        
        
        self.m_panel1.SetSizer( bSizer2 )
        self.m_panel1.Layout()
        bSizer2.Fit( self.m_panel1 )
        bSizer1.Add( self.m_panel1, 0, wx.EXPAND |wx.ALL, 5 )
        
        self.m_panel2 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
        bSizer3 = wx.BoxSizer( wx.HORIZONTAL )
        
        self.m_staticText2 = wx.StaticText( self.m_panel2, wx.ID_ANY, u"숫자2 : ", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.m_staticText2.Wrap( -1 )
        bSizer3.Add( self.m_staticText2, 0, wx.ALL, 5 )
        
        self.txtNum2 = wx.TextCtrl( self.m_panel2, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
        bSizer3.Add( self.txtNum2, 0, wx.ALL, 5 )
        
        
        self.m_panel2.SetSizer( bSizer3 )
        self.m_panel2.Layout()
        bSizer3.Fit( self.m_panel2 )
        bSizer1.Add( self.m_panel2, 0, wx.EXPAND |wx.ALL, 5 )
        
        self.m_panel3 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
        bSizer4 = wx.BoxSizer( wx.VERTICAL )
        
        rdoOpChoices = [ u"+", u"-", u"*", u"/" ]
        self.rdoOp = wx.RadioBox( self.m_panel3, wx.ID_ANY, u"연산자 선택", wx.DefaultPosition, wx.DefaultSize, rdoOpChoices, 1, wx.RA_SPECIFY_ROWS )
        self.rdoOp.SetSelection( 0 )
        bSizer4.Add( self.rdoOp, 1, wx.ALL|wx.EXPAND, 5 )
        
        
        self.m_panel3.SetSizer( bSizer4 )
        self.m_panel3.Layout()
        bSizer4.Fit( self.m_panel3 )
        bSizer1.Add( self.m_panel3, 0, wx.EXPAND |wx.ALL, 5 )
        
        self.m_panel4 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
        bSizer5 = wx.BoxSizer( wx.HORIZONTAL )
        
        self.m_staticText3 = wx.StaticText( self.m_panel4, wx.ID_ANY, u"연산 결과 : ", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.m_staticText3.Wrap( -1 )
        bSizer5.Add( self.m_staticText3, 0, wx.ALL, 5 )
        
        self.staResult = wx.StaticText( self.m_panel4, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
        self.staResult.Wrap( -1 )
        bSizer5.Add( self.staResult, 0, wx.ALL, 5 )
        
        
        self.m_panel4.SetSizer( bSizer5 )
        self.m_panel4.Layout()
        bSizer5.Fit( self.m_panel4 )
        bSizer1.Add( self.m_panel4, 0, wx.EXPAND |wx.ALL, 5 )
        
        self.m_panel5 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
        bSizer6 = wx.BoxSizer( wx.HORIZONTAL )
        
        self.btnCalc = wx.Button( self.m_panel5, wx.ID_ANY, u"계산", wx.DefaultPosition, wx.DefaultSize, 0 )
        bSizer6.Add( self.btnCalc, 0, wx.ALL, 5 )
        
        self.btnClear = wx.Button( self.m_panel5, wx.ID_ANY, u"초기화", wx.DefaultPosition, wx.DefaultSize, 0 )
        bSizer6.Add( self.btnClear, 0, wx.ALL, 5 )
        
        self.btnExit = wx.Button( self.m_panel5, wx.ID_ANY, u"종료", wx.DefaultPosition, wx.DefaultSize, 0 )
        bSizer6.Add( self.btnExit, 0, wx.ALL, 5 )
        
        
        self.m_panel5.SetSizer( bSizer6 )
        self.m_panel5.Layout()
        bSizer6.Fit( self.m_panel5 )
        bSizer1.Add( self.m_panel5, 0, wx.EXPAND |wx.ALL, 5 )
        
        
        self.SetSizer( bSizer1 )
        self.Layout()
        
        self.Centre( wx.BOTH )
        
        # Connect Events
        self.btnCalc.id = 1    # id 직접 추가
        self.btnClear.id = 2
        self.btnExit.id = 3
          
        self.btnCalc.Bind( wx.EVT_BUTTON, self.CalcProcess )
        self.btnClear.Bind( wx.EVT_BUTTON, self.CalcProcess )
        self.btnExit.Bind( wx.EVT_BUTTON, self.CalcProcess )
    
    def __del__( self ):
        pass
    
    # Virtual event handlers, overide them in your derived class
    def CalcProcess( self, event ):    # 메소드 직접 추가
        sel_id = event.GetEventObject().id
        if sel_id == 1:    # 계산
            op = self.rdoOp.GetStringSelection()    # 라디오 버튼 선택 항목 입력
            num1 = self.txtNum1.GetValue()
            num2 = self.txtNum2.GetValue()
            
            if num1 == '' or num2 == '':
                wx.MessageBox('값을 입력하세요', '오류', wx.OK)
                return    # CalcProcess 를 탈출
            
            try:
                calc_Result = eval(num1 + op + num2)    # 계산
            except Exception as e:
                wx.MessageBox('연산오류: ' + str(e), '알림', wx.OK)
                self.staResult.SetLabelText('')    # 오류면 결과창에 아무 것도 출력 안함
            
            self.staResult.SetLabelText(str(calc_Result))    # 결과창에 계산값 출력
                
        elif sel_id == 2:    # 초기화
            self.txtNum1.SetLabel('')
            self.txtNum2.SetLabel('')
            self.staResult.SetLabel('')
            self.rdoOp.SetSelection(0)    # 라디오 버튼 처음으로 돌아감
            self.txtNum1.SetFocus()    # 초기화 했을때 커서가 맨위로 간다
            
        elif sel_id == 3:    # 종료
            dlg = wx.MessageDialog(self, '정말 종료할까요?', '알림', wx.YES_NO)    # 대화 상자 열기
            imsi = dlg.ShowModal()
            if imsi == wx.ID_YES:
                dlg.Destroy()    # 대화 상자 닫기
                self.Close()    # Frame 닫기
                
                
if __name__ == '__main__':
    app = wx.App()
    MyCalc(None).Show()
    app.MainLoop()    # 무한루프에 빠뜨린다
In [14]:
# 출력되는 창
with open('gui6.gif','rb') as file:
    display(Image(file.read()))
Image("gui6_wx.png")
Out[14]:
  Categories :
  
  
      Practice