개요
wxPython에서 여러 개의 윈도우를 관련 탭으로 묶어 표시하는 컨트롤을 노트북(wx.Notebook)이라고 한다. 노트북은 서로 다른 기능적인 부분을 탭으로 각각 묶어 표시하기 때문에 UI가 간결하고 깔끔해지는 장점이 있고, 코드상 관리가 쉽다. 본 글에 포함된 예제에서는 GUI 하단에 노트북을 넣어 총 세 개의 선택컨트롤(wx.~PickerCtrl)들을 보다 쉽게 관리하는 모습을 보여준다.
wx.Notebook
노트북 클래스(wx.Notebook)는 여러 개의 탭으로 이루어진 노트북 페이지를 모두 관리한다. 노트북 안에 속한 각각의 탭들을 노트북 페이지 라고 부른다. 페이지들은 패널(wx.Panel)을 상속해서 만든 클래스이다. 그리고 노트북은 페이지를 포함하므로, 노트북과 페이지의 관계는 메뉴바와 메뉴의 관계와 같다. 과정은 총 3단계이고, 인수는 간단하니 설명을 생략하도록 하겠다.
[1단계. 노트북 선언]
nb = wx.Notebook(parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=0, name="")
위와 같이 노트북을 선언하고 나면, 이제 노트북에 속하는 각각의 페이지들을 선언해주어야 한다. 각 페이지들은 위에서 선언한 노트북(nb) 변수를 부모로 갖는다. 각 페이지를 선언한 뒤, 이를 노트북에 더해주는 코드는 아래와 같다.
[2단계. 페이지 선언]
각 페이지들은 wx.Panel을 상속해서 만든 A,B,C Panel이다. (상속하는 방법은 어렵지 않으니 에제를 참조하자.)
nb_page1 = A_panel(nb)
nb_page2 = B_panel(nb)
nb_page3 = C_panel(nb)
[3단계. 페이지 노트북에 할당]
nb.AddPage(nb_page1, text="페이지1", select=True)
nb.AddPage(nb_page2, text="페이지2", select=False)
nb.AddPage(nb_page3, text="페이지3", select=False)
이렇게 노트북 1개가 완성이 되면, 사이저에 담아주면 끝이다. 사이저는 박스사이저나 기타 다른 사이저들 모두 가능하다.
예제
예제는 노트북(wx.Notebook)을 이용하여 파일선택컨트롤(wx.FilePickerCtrl), 폰트선택컨트롤(wx.FontPickerCtrl), 색상선택컨트롤(wx.ColourPickerCtrl) 세 개를 각각의 페이지에 담아 관리하는 모습을 보여준다. 노트북에 속한 각 페이지들을 어떻게 선언하고 관리하는지 예제를 통해 알아보자.
import wx
class Example(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self,parent,id,'Notebook Example Window', size=(600,600), pos=(150,150))
# 메인 패널
self.panel = wx.Panel(self)
# 최상단 제목
self.title = wx.StaticText(self.panel, -1, "Hexa-Coding 헥사코딩")
# 서브 패널 : 이미지 표시용
self.subpanel = wx.Panel(self.panel, size=(300, 300))
# 노트북 생성
nb = wx.Notebook(self.panel, size=(-1, -1))
"""
노트북 페이지 생성 : 총 3개
"""
# 노트북 탭 아이콘 설정
# 여러 개의 이미지를 동시 할당하기 위해 이미지 리스트(wx.ImageList)를 활용한다.
icon_paths = ['D:/icon/page.png', 'D:/icon/font.png', 'd:/icon/color-palette.png']
icons = wx.ImageList(12,12)
img_idxs = []
for i in range(3):
# 비트맵 이미지 불러오기
bmp = wx.Bitmap(icon_paths[i], wx.BITMAP_TYPE_PNG)
# 이미지 사이즈 조절 (원본 이미지: 32x32 --> 변경 이미지 크기: 11x11)
bmp = self.scale_bitmap(bmp, 12,12)
# 이미지리스트에 비트맵 삽입, idx = Add() 메소드 리턴값. 이미지 인덱스 정수값이 리턴됨.
idx = icons.Add(bmp)
img_idxs.append(idx)
# 노트북 패널 생성
nb_page1 = FilePanel(nb)
nb_page2 = FontPanel(nb)
nb_page3 = ColorPanel(nb)
# 노트북 탭 이름
tab_name = ['파일', '글꼴', '색상']
nb.AddPage(nb_page1, text=tab_name[0], select=False)
nb.AddPage(nb_page2, text=tab_name[1], select=False)
nb.AddPage(nb_page3, text=tab_name[2], select=False)
# 노트북 탭에 이미지 할당
nb.AssignImageList(icons)
for i in range(3):
nb.SetPageImage(i, img_idxs[i])
# 박스사이저에 노트북 할당
bsizer = wx.BoxSizer(wx.VERTICAL)
bsizer.Add(self.title, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 30)
bsizer.Add(self.subpanel, 1, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 10)
bsizer.Add(nb, 0, wx.ALL|wx.EXPAND, 10)
self.panel.SetSizer(bsizer)
self.panel.Layout()
# 이미지 스케일 조절
def scale_bitmap(self, bmp, w, h):
img = wx.Bitmap.ConvertToImage(bmp)
img = img.Scale(w,h, wx.IMAGE_QUALITY_HIGH)
result = wx.Bitmap(img)
return result
# 노트북(wx.Notebook) 파일 패널
class FilePanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent=parent)
# 파일선택컨트롤
self.filepick = wx.FilePickerCtrl(self, id=-1, path="D:/icon/", message="PNG 파일을 선택하세요", size=(-1, -1),
wildcard="PNG files (*.png)|*.png", style=wx.FLP_DEFAULT_STYLE)
self.nbsizer = wx.BoxSizer(wx.VERTICAL)
self.nbsizer.Add(self.filepick, 0, wx.ALL|wx.EXPAND, 10)
self.SetSizer(self.nbsizer)
self.Bind(wx.EVT_FILEPICKER_CHANGED, lambda e: self.OnFilePicked(self.filepick, e))
# 파일선택컨트롤 버튼 클릭시 동작
def OnFilePicked(self, filepick, e):
import os
# 설정한 아이디로 Frame 인스턴스 확인
frame = wx.FindWindowById(1)
# 선택한 파일 경로
path = self.filepick.GetPath()
# 파일 확장자명이 .png로 끝날 때 수행
if os.path.basename(path).endswith('.png'):
# 이미지 불러오기
img = wx.Image(path, type=wx.BITMAP_TYPE_PNG)
# 이미지를 비트맵으로 변환
bmp = wx.Bitmap(img)
# 비트맵 크기조절
bmp = frame.scale_bitmap(bmp, 300,300)
# 비트맵을 subpanel에 표시 (id=1001)
bmp = wx.StaticBitmap(frame.subpanel, 1001, bmp)
# 레이아웃 재설정
self.nbsizer.Layout()
# 노트북(wx.Notebook) 글꼴 패널
class FontPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent=parent)
# 폰트선택컨트롤 생성
fontpick = wx.FontPickerCtrl(self, id=-1, font=wx.NullFont, style=wx.FNTP_DEFAULT_STYLE)
nbsizer = wx.BoxSizer(wx.VERTICAL)
nbsizer.Add(fontpick, 0, wx.ALL|wx.EXPAND, 10)
self.SetSizer(nbsizer)
# 폰트선택컨트롤 바인딩
self.Bind(wx.EVT_FONTPICKER_CHANGED, lambda e: self.OnFontPicked(fontpick, e))
def OnFontPicked(self, fontpick, e):
# 설정한 아이디로 Frame 인스턴스 확인
frame = wx.FindWindowById(1)
# 폰트 선택 확인
font = fontpick.GetSelectedFont()
# 폰트 색상 확인
color = fontpick.GetSelectedColour()[:-1] # 맨 마지막 alpha 값은 삭제한다
# 폰트 변경
frame.title.SetFont(font)
# 폰트 색상 변경
frame.title.SetForegroundColour(color)
# 레이아웃
frame.panel.Layout()
# 노트북(wx.Notebook) 색상 패널
class ColorPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent=parent)
# 컬러선택컨트롤 생성
colorpick = wx.ColourPickerCtrl(self, id=-1, colour=wx.BLACK, style=wx.CLRP_DEFAULT_STYLE)
nbsizer = wx.BoxSizer(wx.VERTICAL)
nbsizer.Add(colorpick, 0, wx.ALL | wx.EXPAND, 10)
self.SetSizer(nbsizer)
# 폰트컨트롤 바인딩
self.Bind(wx.EVT_COLOURPICKER_CHANGED, lambda e: self.OnColorPicked(colorpick, e))
def OnColorPicked(self, colorpick, e):
# 설정한 아이디로 Frame 인스턴스 확인
frame = wx.FindWindowById(1)
# 컬러 선택 확인
color = colorpick.GetColour()[:-1]
# 아이디로 엠블럼 비트맵 확인
staticbmp = wx.FindWindowById(1001)
bmp = staticbmp.GetBitmap()
# 엠블럼 있으면,
if bmp:
# 비트맵을 이미지로 변경
img = wx.Bitmap.ConvertToImage(bmp)
# 이미지 색상 변경 검정색(0,0,0) -> 선택한 색상(*color)
img.Replace(0,0,0,*color)
# 색상 변경된 신규 비트맵
bmp_new = wx.Bitmap(img)
# 스태틱 비트맵 컨트롤에 신규 비트맵 삽입
staticbmp.SetBitmap(bmp_new)
# 레이아웃
frame.panel.Layout()
if __name__=="__main__":
app = wx.App()
frame=Example(parent=None, id=1)
frame.Show()
app.MainLoop()
도움되셨다면 하트(♥) 부탁드리고, 더 궁금한 사항은 댓글로 남겨주세요 :)
'wxPython' 카테고리의 다른 글
파이썬 GUI, 파이비지인포 PyBusyInfo (0) | 2023.03.21 |
---|---|
파이썬 GUI, 풍선 팁 BalloonTip (0) | 2023.03.21 |
파이썬 GUI, 파일선택컨트롤 wx.FilePickerCtrl (0) | 2023.03.18 |
파이썬 GUI, 스태틱박스 사이저 wx.StaticBoxSizer (0) | 2023.03.12 |
파이썬 GUI, 플렉시 그리드 사이저 wx.FlexiGridSizer (0) | 2023.03.12 |