빅데이터 프로그래밍/Python

[Python] 19. [GUI] wxPython 그래픽 사용자 인터페이스, 다양한 Widget, Menu

밍글링글링 2017. 8. 2.
728x90

01. 다양한 Widget

1 wx.MenuBar, wx.Menu, wx.MenuItem 위젯을 통한 메뉴의 출력

- wx.MenuBar: 화면 상/하단위 메뉴바
- wx.Menu: 메뉴바에 붙이는 메뉴 그룹 한 열
- wx.MenuItem: 메뉴열에 붙이는 하나의 메뉴 항목

- wx.MenuBar(): 메뉴들의 구성
- fileNewMenu = fileMenu.Append(wx.ID_ANY, "새 파일"): 메뉴 항목 추가
- fileMenu.AppendSeparator(): 메뉴 구분자
- self.menuBar.Append(fileMenu, "&File"): 메뉴바에 메뉴 붙이기  
- self.Bind(wx.EVT_MENU, self.OnNew, fileNewMenu): 이벤트 등록 

▷ /wxexam/Menu.py
-------------------------------------------------------------------------------------
# -*- coding: utf-8 -*-

import wx

class MyFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, parent=None, title="Menu Example")
            
        self.menuBar = wx.MenuBar()
        fileMenu = wx.Menu()
        fileNewMenu = fileMenu.Append(wx.ID_ANY, "새 파일")
        fileOpenMenu = fileMenu.Append(wx.ID_ANY, "열기")
        fileMenu.AppendSeparator()  # 구분자
        fileExitMenu = fileMenu.Append(wx.ID_ANY, "끝내기")

        customMenu = wx.Menu()
        customHelloMenu = customMenu.Append(wx.ID_ANY, "&Hello", )
        
        self.menuBar.Append(fileMenu, "&File")   # 메뉴바에 메뉴 붙이기
        self.menuBar.Append(customMenu, "&Test") # 메뉴바에 메뉴 붙이기
        
        self.SetMenuBar(self.menuBar) # 메뉴바를 윈도우에 붙이기

        # 이벤트 등록(이벤트 종류, 핸들러 함수, men 항목)
        self.Bind(wx.EVT_MENU, self.OnNew, fileNewMenu) 
        self.Bind(wx.EVT_MENU, self.OnOpen, fileOpenMenu)
        self.Bind(wx.EVT_MENU, self.OnExit, fileExitMenu)        
        self.Bind(wx.EVT_MENU, self.OnHello, customHelloMenu)
    
    def OnNew(self, e):
        wx.MessageBox("OnNew() Clicked!") # [OK] 버튼 옵션

    def OnOpen(self, e):
        wx.MessageBox("OnOpen() Clicked!")

    def OnExit(self, e):
        self.Close()  # 현재 화면 끝내기 

    def OnHello(self, e):
        wx.MessageBox("Hello.");

if __name__ == "__main__":
    app = wx.App()
    frame = MyFrame()
    frame.Show()

    app.MainLoop()
    
    

-------------------------------------------------------------------------------------

 

2. wx.StaticText, wx.TextCtrl
- wx.StaticText: 문자열 출력
- wx.TextCtrl: 문자열 입력/ 출력 지원

▷ /wxexam/TextCtrl.py
-------------------------------------------------------------------------------------
# -*- coding: utf-8 -*-

import wx

class MyFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, parent=None, title="TextCtrl Example")
        self.SetSize(500, 300)
        self.mainPanel = wx.Panel(self)
        
        self.staticRed = wx.StaticText(self.mainPanel, label="Red : ")
        self.textRed = wx.TextCtrl(self.mainPanel, value='255')
        
        self.staticGreen = wx.StaticText(self.mainPanel, label="Green : ")
        self.textGreen = wx.TextCtrl(self.mainPanel, value='255')
        
        self.staticBlue = wx.StaticText(self.mainPanel, label="Blue : ")
        self.textBlue = wx.TextCtrl(self.mainPanel, value='255')
        
        self.gridSizer = wx.GridSizer(rows=3, cols=2, hgap=5, vgap=5)
        self.gridSizer.Add(self.staticRed)
        self.gridSizer.Add(self.textRed, 0, wx.EXPAND)
        self.gridSizer.Add(self.staticGreen)
        self.gridSizer.Add(self.textGreen, 0, wx.EXPAND)
        self.gridSizer.Add(self.staticBlue)
        self.gridSizer.Add(self.textBlue, 0, wx.EXPAND)

        self.vtBoxSizer = wx.BoxSizer(wx.VERTICAL)
        self.vtBoxSizer.Add(self.gridSizer, 1, wx.EXPAND|wx.ALL, 10)
        self.mainPanel.SetSizer(self.vtBoxSizer)

        self.Bind(wx.EVT_TEXT, self.OnTextChange, self.textRed)
        self.Bind(wx.EVT_TEXT, self.OnTextChange, self.textGreen)
        self.Bind(wx.EVT_TEXT, self.OnTextChange, self.textBlue)
        self.ChangeColor()

    def OnTextChange(self, e):
        self.ChangeColor();

    def ChangeColor(self):
        r = int(self.textRed.GetValue()) # TextCtrl에서 문자열로 값 산출
        g = int(self.textGreen.GetValue())
        b = int(self.textBlue.GetValue())
        self.mainPanel.SetBackgroundColour(wx.Colour(r, g, b))
        self.mainPanel.Refresh()  # 적용

if __name__ == "__main__":
    app = wx.App()
    frame = MyFrame()
    frame.Show()

    app.MainLoop()


-------------------------------------------------------------------------------------
 
3. wx.RadioButton
- Radio 버튼
- StaticBox는 Panel과 비슷하지만 상단에 Label을 출력
- wx.RadioButton(self.mainBox, label="Red", style=wx.RB_GROUP): 그룹의 시작 선언
▷ /wxexam/RadioButton.py
-------------------------------------------------------------------------------------
# -*- coding: utf-8 -*-

import wx

class MyFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, parent=None, title="RadioButton Example")
        self.SetSize(500, 300)
        self.mainPanel = wx.Panel(self)
        self.mainBox = wx.StaticBox(self.mainPanel, label="색깔 지정하기")

        # style=wx.RB_GROUP: 새로운 그룹의 시작
        self.rdoRed     = wx.RadioButton(self.mainBox, label="Red", style=wx.RB_GROUP)
        self.rdoGreen   = wx.RadioButton(self.mainBox, label="Green")
        self.rdoBlue    = wx.RadioButton(self.mainBox, label="Blue")
        
        self.rdoEnable  = wx.RadioButton(self.mainBox, label="Enable", style=wx.RB_GROUP)
        self.rdoDisable = wx.RadioButton(self.mainBox, label="Disable")
        
        self.gridSizer = wx.GridSizer(rows=2, cols=3, hgap=5, vgap=15)
        self.gridSizer.Add(self.rdoRed)
        self.gridSizer.Add(self.rdoGreen)
        self.gridSizer.Add(self.rdoBlue)
        self.gridSizer.Add(self.rdoEnable)
        self.gridSizer.Add(self.rdoDisable)

        self.vtBoxSizer = wx.BoxSizer(wx.VERTICAL)
        self.vtBoxSizer.Add(self.gridSizer, 1, wx.EXPAND|wx.ALL, 15)
        self.mainBox.SetSizer(self.vtBoxSizer)

        self.mainSizer = wx.BoxSizer(wx.VERTICAL)
        self.mainSizer.Add(self.mainBox, 1, wx.EXPAND|wx.ALL, 5)
        self.mainPanel.SetSizer(self.mainSizer)

        self.Bind(wx.EVT_RADIOBUTTON, self.OnRed, self.rdoRed)
        self.Bind(wx.EVT_RADIOBUTTON, self.OnGreen, self.rdoGreen)
        self.Bind(wx.EVT_RADIOBUTTON, self.OnBlue, self.rdoBlue)
        self.Bind(wx.EVT_RADIOBUTTON, self.OnEnable, self.rdoEnable)
        self.Bind(wx.EVT_RADIOBUTTON, self.OnDisable, self.rdoDisable)

    def OnRed(self, e):
        self.mainBox.SetBackgroundColour(wx.Colour(255, 0, 0))
        self.mainBox.Refresh()

    def OnGreen(self, e):
        self.mainBox.SetBackgroundColour(wx.Colour(0, 255, 0))
        self.mainBox.Refresh()

    def OnBlue(self, e):
        self.mainBox.SetBackgroundColour(wx.Colour(0, 0, 255))
        self.mainBox.Refresh()

    def OnEnable(self, e):
        self.rdoRed.Enable(True)  # 활성화
        self.rdoGreen.Enable(True)
        self.rdoBlue.Enable(True)

    def OnDisable(self, e):
        self.rdoRed.Enable(False)  # 비활성화
        self.rdoGreen.Enable(False)
        self.rdoBlue.Enable(False)
        

if __name__ == "__main__":
    app = wx.App()
    frame = MyFrame()
    frame.Show()

    app.MainLoop()
    
    
-------------------------------------------------------------------------------------
 

4. wx.CheckBox
- self.checkBold.SetValue(wx.CHK_CHECKED): 체크 상태 설정
- self.checkItalic.SetValue(wx.CHK_UNCHECKED): 체크하지 않는 상태 설정
-self.vtBoxSizer.Add(self.checkBold, 1, wx.ALL, 5): wx.ALL 명령은 모든면에 border 값을 지정하는 것이나 좌측 정렬 효과도 있음.
https://wxpython.org/Phoenix/docs/html/search.html?q=CommandEvent

▷ /wxexam/CheckBox.py
-------------------------------------------------------------------------------------
# -*- coding: utf-8 -*-

import wx

class MyFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, parent=None, title="CheckBox Example")
        self.SetSize(500, 300)
        self.mainPanel = wx.Panel(self)
        
        self.checkBold = wx.CheckBox(self.mainPanel, label="Bold")
        self.checkBold.SetValue(wx.CHK_CHECKED) # 체크 설정

        self.checkItalic = wx.CheckBox(self.mainPanel, label="Italic")
        self.checkItalic.SetValue(wx.CHK_UNCHECKED) # 체크 미설정
        
        self.staticText = wx.StaticText(self.mainPanel, label="I am a Programmer.")        

        self.vtBoxSizer = wx.BoxSizer(wx.VERTICAL)
        self.vtBoxSizer.Add(self.checkBold, 1, wx.ALL, 5)
        self.vtBoxSizer.Add(self.checkItalic, 1, wx.ALL, 5)
        self.vtBoxSizer.Add(self.staticText, 1, wx.EXPAND | wx.ALL, 5)
        self.mainPanel.SetSizer(self.vtBoxSizer)

        self.Bind(wx.EVT_CHECKBOX, self.OnCheck, self.checkBold)
        self.Bind(wx.EVT_CHECKBOX, self.OnCheck, self.checkItalic)
        self.ChangeFont() # 초기 설정

    def OnCheck(self, evt):
        print('type(evt): ' + str(type(evt)))
        print('type(evt.GetString()): ' + str(evt.GetString()))
        print('type(evt.GetSelection()): ' + str(evt.GetSelection()))
        print('type(evt.IsChecked()): ' + str(evt.IsChecked()))
        print('type(evt.Selection): ' + str(evt.Selection))
        self.ChangeFont()

    def ChangeFont(self):
        style = wx.FONTSTYLE_NORMAL
        weight = wx.FONTWEIGHT_NORMAL

        if self.checkBold.GetValue() == wx.CHK_CHECKED:
            weight = wx.FONTWEIGHT_BOLD
        if self.checkItalic.GetValue() == wx.CHK_CHECKED:
            style = wx.FONTSTYLE_ITALIC

        font = wx.Font(30, wx.FONTFAMILY_DEFAULT, style, weight)
        self.staticText.SetFont(font)

if __name__ == "__main__":
    app = wx.App()
    frame = MyFrame()
    frame.Show()

    app.MainLoop()
    
    


-------------------------------------------------------------------------------------
 
5. wx.ListBox, wx.ComboBox
- self.colorCombo = wx.ComboBox(self.mainPanel, choices=colors, style=wx.CB_READONLY): Panel, 선택값, 편집 기능 해제
▷ /wxexam/ListCombo.py
-------------------------------------------------------------------------------------
# -*- coding: utf-8 -*-

import wx

class MyFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, parent=None, title="Combo/ListBox Example")
        self.SetSize(420, 250)
        self.mainPanel = wx.Panel(self)
        
        colors = ["Red", "Orange", "Yellow", "Green", "Blue"]
        self.colorCombo = wx.ComboBox(self.mainPanel, choices=colors, style=wx.CB_READONLY, size=wx.Size(100, 200))
        
        self.colorListBox = wx.ListBox(self.mainPanel, size=wx.Size(100, 200))
        
        self.hzBoxSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.hzBoxSizer.Add(self.colorCombo, 0, wx.ALL, 5) # 콤보 박스
        self.hzBoxSizer.Add(self.colorListBox, 0, wx.ALL, 5) # 리스트 박스
        self.mainPanel.SetSizer(self.hzBoxSizer)

        # 이벤트 등록
        self.Bind(wx.EVT_COMBOBOX, self.OnComboBox, self.colorCombo)
        self.Bind(wx.EVT_LISTBOX, self.OnListBox, self.colorListBox)

    def OnComboBox(self, e):
        idx = self.colorCombo.GetCurrentSelection() # 선택된 index 0
        print('idx: ' + str(idx))
        print('self.colorCombo.Items[idx]: ' + self.colorCombo.Items[idx])
        self.colorListBox.Append(self.colorCombo.Items[idx])

    def OnListBox(self, e):
        idx = self.colorListBox.GetSelection()
        # self.colorCombo.Append("List 클릭 발생")
        wx.MessageBox(self.colorListBox.Items[idx]) # [OK]

if __name__ == "__main__":
    app = wx.App()
    frame = MyFrame()
    frame.Show()

    app.MainLoop()
    
     

-------------------------------------------------------------------------------------
 
6. wx.TreeCtrl
- 메뉴의 출력
- root = self.tree.AddRoot('태조'): 최초 메뉴 등록
- self.tree.AppendItem(root, '방우'): 메뉴 등록
- taejong = self.tree.AppendItem(root, '태종(방원)'): 하위 메뉴 구성
- self.tree.AppendItem(taejong, '양녕'): 새로운 하위 메뉴에 메뉴 등록

▷ /wxexam/TreeCtrl.py
-------------------------------------------------------------------------------------
# -*- coding: utf-8 -*-

import wx

class MyFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, parent=None, title="TreeCtrl Example")
        self.SetSize(420, 320)
        self.mainPanel = wx.Panel(self)
        self.expandButton = wx.Button(self.mainPanel, label="Expand")        

        self.tree = wx.TreeCtrl(self.mainPanel)
        root = self.tree.AddRoot('태조')
        self.tree.AppendItem(root, '방우')
        self.tree.AppendItem(root, '정종(방과)')
        self.tree.AppendItem(root, '방의')
        self.tree.AppendItem(root, '방간')
        taejong = self.tree.AppendItem(root, '태종(방원)')
        self.tree.AppendItem(root, '방연')

        self.tree.AppendItem(taejong, '양녕')
        self.tree.AppendItem(taejong, '효령')
        self.tree.AppendItem(taejong, '세종(충녕)')
        self.tree.AppendItem(taejong, '효령')

        self.staticText = wx.StaticText(self.mainPanel, style=wx.ALIGN_CENTER)
                    
        self.vtBoxSizer = wx.BoxSizer(wx.VERTICAL)    
            
        self.vtBoxSizer.Add(self.expandButton, 0, wx.EXPAND|wx.ALL, 5)
        self.vtBoxSizer.Add(self.tree, 1, wx.EXPAND|wx.ALL, 5)
        self.vtBoxSizer.Add(self.staticText, 0, wx.EXPAND|wx.ALL, 5)
        
        self.mainPanel.SetSizer(self.vtBoxSizer)

        self.Bind(wx.EVT_BUTTON, self.OnExpandButton, self.expandButton)
        
        # 트리 노드 클릭시
        self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnNodeSelected, self.tree)

    def OnExpandButton(self, e):
        self.tree.ExpandAll()  # 트리메뉴 전부 펼침

    def OnNodeSelected(self, e):
        selected = self.tree.GetSelection() # 0 ~
        self.staticText.SetLabel(self.tree.GetItemText(selected))
        self.mainPanel.Layout() # staticText 위젯의 크기 변경되어 다시 Layout 적용
        
if __name__ == "__main__":
    app = wx.App()
    frame = MyFrame()
    frame.Show()

    app.MainLoop()
    
    

-------------------------------------------------------------------------------------
 
7. wx.Slider, wx.Gauge
- wx.Slider: 볼륨등 사용자의 입출력 처리
- wx.Gauge: 연료의 상태등 출력
▷ /wxexam/SliderGuage.py
-------------------------------------------------------------------------------------
# -*- coding: utf-8 -*-

import wx

class MyFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, parent=None, title="Slider & Gauge")
        self.SetSize(500, 120)
        self.mainPanel = wx.Panel(self)

        self.slider = wx.Slider(self.mainPanel, minValue=0, maxValue=100)
        self.gauge = wx.Gauge(self.mainPanel, range=200)        
                    
        self.vtBoxSizer = wx.BoxSizer(wx.VERTICAL)        
        self.vtBoxSizer.Add(self.slider, 0, wx.EXPAND|wx.ALL, 5)
        self.vtBoxSizer.Add(self.gauge, 0, wx.EXPAND|wx.ALL, 5)
        self.mainPanel.SetSizer(self.vtBoxSizer)
        
        # 이벤트 등록
        self.Bind(wx.EVT_SLIDER, self.OnSliderChange, self.slider)

    def OnSliderChange(self, e):
        self.gauge.SetValue(self.slider.GetValue())
                
if __name__ == "__main__":
    app = wx.App()
    frame = MyFrame()
    frame.Show()

    app.MainLoop()
    
    
-------------------------------------------------------------------------------------
 
8. wx.Dialog
- dlg.ShowModal(): dialog를 닫기전에 부모창을 이용할 수 없음.
- dlg.Show(): dialog를 닫기전에 부모창을 이용할 수 있음.      
▷ /wxexam/Dialog.py
-------------------------------------------------------------------------------------
# -*- coding: utf-8 -*-

import wx

class MyDialog(wx.Dialog):
    # _parent: 부모 Frame, _title: 창 제목
    def __init__(self, _parent, _title):
        wx.Dialog.__init__(self, parent=_parent, title=_title)
        self.SetSize(300, 150)
        self.mainPanel = wx.Panel(self)        
        self.closeButton = wx.Button(self.mainPanel, label="Close")

        self.vtBoxSizer = wx.BoxSizer(wx.VERTICAL)        
        self.vtBoxSizer.Add(self.closeButton, 0, wx.ALIGN_CENTER|wx.ALL, 40)
        self.mainPanel.SetSizer(self.vtBoxSizer)

        self.Bind(wx.EVT_BUTTON, self.OnClose, self.closeButton)
        self.Bind(wx.EVT_CLOSE, self.OnClose) # Dialog 에 이벤트 등록

    def OnClose(self, e):        
        self.Destroy()
        
class MyFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, parent=None, title="Modal & Modeless")
        self.SetSize(500, 300)
        self.mainPanel = wx.Panel(self)

        self.modalButton = wx.Button(self.mainPanel, label="Modal")
        self.ModelessButton = wx.Button(self.mainPanel, label="Modeless")
                     
        self.fgridSizer = wx.FlexGridSizer(rows=1, cols=2, hgap=5, vgap=5) 
        
        self.fgridSizer.Add(self.modalButton, 0, wx.ALIGN_LEFT|wx.ALL, 5)
        self.fgridSizer.Add(self.ModelessButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
        
        self.fgridSizer.AddGrowableCol(1) # 화면 크기에따라 두번째 컬럼 반영
        self.mainPanel.SetSizer(self.fgridSizer)

        self.Bind(wx.EVT_BUTTON, self.OnModalButton, self.modalButton)
        self.Bind(wx.EVT_BUTTON, self.OnModelessButton, self.ModelessButton)

    def OnModalButton(self, e):
        dlg = MyDialog(self, "Modal Dialog")
        dlg.ShowModal()

    def OnModelessButton(self, e):
        dlg = MyDialog(self, "Modeless Dialog")
        dlg.Show()        

if __name__ == "__main__":
    app = wx.App()
    frame = MyFrame()
    frame.Show()

    app.MainLoop()
    
    
-------------------------------------------------------------------------------------
 

728x90

댓글