본문 바로가기

wxPython

파이썬 GUI, 파일컨트롤 wx.FileCtrl

반응형

 

 

개요 

    파일컨트롤(wx.FileCtrl)스태틱텍스트(wx.StaticText), 리스트컨트롤(wx.ListCtrl), 텍스트컨트롤(wx.TextCtrl), 그리고 콤보상자(wx.ComboBox)의 조합으로 이루어진 위젯이다. 기본적으로 폴더를 자유롭게 왔다갔다 할 수 있고, 파일을 선택할 수 있다. 예제에서는 파일컨트롤을 이용하여 그림파일을 열고, 또 회전도 시킬 수 있는 팝업메뉴를 구성하였다. 

 

 

wx.FileCtrl

    파일컨트롤은 아래와 같이 선언한다. 

fc = wx.FileCtrl(parent, id=ID_ANY, defaultDirectory="",
                 defaultFilename="", wildCard="All Files(*.*)|*.*",
                 style=wx.FC_DEFAULT_STYLE, pos=wx.DefaultPosition, size=wx.DefaultSize,
                 name="")

    parent: 부모클래스 

    id: 아이디 

    defaultDirectory: 기본디렉토리. 맨 처음 보여주는 폴더. 빈 문자열이면 현재 작업디렉토리를 띄운다. (os.getcwd())

    defaultFilename: 기본파일명. 

    wildcard: 파일컨트롤에 보여질 파일 필터라고 생각하면된다. 와일드카드로 지정된 파일 확장자만 보여진다. 

    style: 스타일은 wx.FC_DEFAULT_STYLE을 포함하여 파일을 열 때 적합한 wx.FC_OPEN, 저장할 때 적합한 wx.FC_SAVE, 여러 파일을 한 번에 선택할 수 있는 wx.FC_MULTIPLE, 그리고 마지막으로 숨김파일을 보여줄지 체크박스를 별도로 생성하는 wx.FC_NOSHOWHIDDEN이 있다. 이 조건들은 서로 상충되어 같이 사용할 수 없는 것들도 있으니 동시 사용에 주의하자. 

    pos: 위치 (x,y)

    size: 크기 (x,y)

    name: 위젯이름 

 

    

예제 

    아래 예제는 파일컨트롤에서 PNG 파일을 더블클릭하면 우측 패널에 그림이 뜨는 예제이다. 또 파일 선택 후 마우스 우클릭을 하면 팝업메뉴가 뜨고, 그림을 오른쪽으로 회전시키거나, 왼쪽으로 회전시킬 수 있다. (그 외 다른 메뉴들은 구현하지 않았다.) 파일컨트롤을 이용하여 파일을 여는 법과 함께 그림파일을 다루는 법도 알아보자. 

반응형
import wx

class Example(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self,parent,id,'Example Window', size=(950,500))

        panel = wx.Panel(self, -1)

        # 이미지 디스플레이용 패널
        self.png_panel = wx.Panel(panel, -1)
        self.png_panel.SetBackgroundColour((220,220,220))
        self.sbmp = wx.StaticBitmap(self.png_panel, -1)

        # 파일컨트롤
        fileCtrl = wx.FileCtrl(panel, 321, defaultDirectory="D:/",pos=wx.DefaultPosition, size=(300,-1),
                               defaultFilename="", wildCard="All Files (*.*)|*.*",
                               style=wx.FC_DEFAULT_STYLE|wx.FC_MULTIPLE|wx.FC_NOSHOWHIDDEN)

        # 초기 기본 디렉토리 설정
        fileCtrl.SetDirectory("d:/icon/")
        # 박스사이저
        bsizer = wx.BoxSizer(wx.HORIZONTAL)
        bsizer.Add(fileCtrl, 0, wx.ALL|wx.EXPAND, 20)
        bsizer.Add(self.png_panel,1, wx.TOP|wx.BOTTOM|wx.RIGHT|wx.EXPAND, 20)

        panel.SetSizer(bsizer)
        self.Center()


        # 파일 선택시 이벤트
        self.Bind(wx.EVT_FILECTRL_SELECTIONCHANGED, self.OnSelectionChanged)
        # 파일 우클릭
        self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnRightClicked)

        # 파일 더블클릭
        self.Bind(wx.EVT_FILECTRL_FILEACTIVATED, self.OnDClicked)
        # 백스페이스
        fileCtrl.Bind(wx.EVT_CHAR_HOOK, self.OnBackSpace)
        fileCtrl.SetFocus()

    # 파일 더블클릭
    def OnDClicked(self,e):
        fileCtrl = e.GetEventObject()
        # 선택된 파일경로
        path = fileCtrl.GetPaths()[0]
        # png 파일인 경우,
        if path.endswith('.png'):
            # 비트맵 생성
            bmp = wx.Bitmap(wx.Image(path, type=wx.BITMAP_TYPE_PNG).Scale(300,300))
            # 비트맵 레이블 할당
            self.sbmp.SetBitmap(bmp)
            # 그림 가운데 표시
            self.sbmp.Center()

    # 파일 선택시 동작
    def OnSelectionChanged(self,e):
        fileCtrl =  e.GetEventObject()
        selected_files = fileCtrl.GetFilenames()

    # PNG 그림파일 우클릭시 메뉴
    def OnRightClicked(self,e):
        # 파일컨트롤 객체 반환
        fileCtrl = e.GetEventObject().GetParent()
        # 파일컨트롤에서 선택된 파일 이름 리스트 반환
        fnames = fileCtrl.GetFilenames()
        import os
        # 파일 확장자 분리
        ext = set([os.path.splitext(e)[-1] for e in fnames])
        if ext=={'.png'}:
            # 마우스 커서 위치 확인
            import pyautogui
            x,y = pyautogui.position()
            # 이벤트 오브젝트 확인
            obj = e.GetEventObject()
            # 팝업메뉴생성
            pop = PopupMenu(self)
            self.PopupMenu(pop, (x/2,y/2)) # 모니터 별 스케일팩터는 다름.. (1 또는 2)
            pop.Destroy()

    # 백스페이스 누르면
    def OnBackSpace(self,e):
        # 키코드 확인 (숫자값)
        key = e.GetKeyCode()
        e_obj = e.GetEventObject().GetParent() # 파일컨트롤 객체 반환
        # 백스페이스 누르면,
        if e_obj.GetName() == 'wxfilectrl' and key==8:
            e_obj.SetFocus()
            # 뒤로가기
            dirpath = e_obj.GetDirectory()
            from pathlib import Path
            path = Path(dirpath)
            # 부모디렉토리 경로 확인
            pdir = path.parent.absolute()
            # 파일컨트롤 경로 변경 (부모디렉토리)
            e_obj.SetDirectory(str(pdir))
        else:
            # if 조건에 해당안되는 경우 이벤트 스킵
            e.Skip()



# 서브메뉴
class SubMenu(wx.Menu):
    def __init__(self):
        wx.Menu.__init__(self)


        # 메뉴아이콘
        img_paint = wx.Bitmap(wx.Image("d:/icon/win/paint.png").Scale(16,16))
        img_pic = wx.Bitmap(wx.Image("d:/icon/win/pic.png").Scale(16,16))
        img_snipping = wx.Bitmap(wx.Image("d:/icon/win/snipping.png").Scale(16, 16))
        img_store = wx.Bitmap(wx.Image("d:/icon/win/microsoft.png").Scale(16, 16))
        img_others = wx.Bitmap(wx.Image("d:/icon/win/others.png").Scale(16, 16))


        # 메뉴아이템
        paint = wx.MenuItem(self, 201, "그림판")
        pic = wx.MenuItem(self, 202, "사진")
        snipping = wx.MenuItem(self, 203, "캡쳐도구")
        store = wx.MenuItem(self, 204, "Microsoft Store 검색")
        others = wx.MenuItem(self, 205, "다른 앱 검색")

        # 아이콘
        paint.SetBitmap(img_paint)
        pic.SetBitmap(img_pic)
        snipping.SetBitmap(img_snipping)
        store.SetBitmap(img_store)
        others.SetBitmap(img_others)

        # 메뉴(wx.Menu)에 등록 
        self.Append(paint)
        self.Append(pic)
        self.Append(snipping)
        self.Append(store)
        self.AppendSeparator()  # 구분자
        self.Append(others)
        

# 팝업메뉴
class PopupMenu(wx.Menu):
    def __init__(self, frame):
        wx.Menu.__init__(self)

        self.frame = frame

        # 아이콘
        img_cut = wx.Bitmap(wx.Image("d:/icon/win/cut.png").Scale(16,16))
        img_copy = wx.Bitmap(wx.Image("d:/icon/win/copy.png").Scale(16, 16))
        # 메뉴 아이콘
        img_open = wx.Bitmap(wx.Image("d:/icon/win/open.png").Scale(16,16))
        img_program = wx.Bitmap(wx.Image("d:/icon/win/program.png").Scale(16, 16))
        img_setbg = wx.Bitmap(wx.Image("d:/icon/win/background.png").Scale(16, 16))
        img_rotater = wx.Bitmap(wx.Image("d:/icon/win/rotate-right.png").Scale(16, 16))
        img_rotatel = wx.Bitmap(wx.Image("d:/icon/win/rotate-left.png").Scale(16, 16))
        img_zip = wx.Bitmap(wx.Image("d:/icon/win/zip-file.png").Scale(16, 16))
        img_copyto = wx.Bitmap(wx.Image("d:/icon/win/copyto.png").Scale(16, 16))
        img_pref = wx.Bitmap(wx.Image("d:/icon/win/pref.png").Scale(16, 16))
        img_options = wx.Bitmap(wx.Image("d:/icon/win/moreoptions.png").Scale(16, 16))


        # 메뉴 아이템 생성
        cut = wx.MenuItem(self, wx.ID_CUT, "", "잘라내기\t(Ctrl+X)")
        copy = wx.MenuItem(self, wx.ID_COPY, "", "복사\t(Ctrl+C)")

        open = wx.MenuItem(self, 101, "열기")
        # 서브메뉴 구성
        set_bg = wx.MenuItem(self, 103, "바탕 화면 배경으로 설정")
        rotate_r = wx.MenuItem(self, 104, "오른쪽으로 회전")
        rotate_l = wx.MenuItem(self, 105, "왼쪽으로 회전")
        zip = wx.MenuItem(self, 106, "ZIP 파일로 압축")
        copy_to = wx.MenuItem(self, 107, "경로로 복사")
        preference = wx.MenuItem(self, 108, "속성\tAlt+Enter")
        options = wx.MenuItem(self, 109, "더 많은 옵션 표시\t Shift+F10")

        # 메뉴에 아이템 연결
        self.Append(cut)
        self.Append(copy)
        self.AppendSeparator() # 구분자
        self.Append(open)
        program = self.AppendSubMenu(SubMenu(), '연결 프로그램', )
        self.Append(set_bg)
        self.Append(rotate_r)
        self.Append(rotate_l)
        self.Append(zip)
        self.Append(copy_to)
        self.Append(preference)
        self.AppendSeparator()  # 구분자
        self.Append(options)

        # 메뉴 아이템에 이미지 연결
        cut.SetBitmap(img_cut)
        copy.SetBitmap(img_copy)
        open.SetBitmap(img_open)
        program.SetBitmap(img_program)
        set_bg.SetBitmap(img_setbg)
        rotate_r.SetBitmap(img_rotater)
        rotate_l.SetBitmap(img_rotatel)
        zip.SetBitmap(img_zip)
        copy_to.SetBitmap(img_copyto)
        preference.SetBitmap(img_pref)
        options.SetBitmap(img_options)

        # 메뉴 아이템 클릭시 이벤트 바인딩
        # 코드가 복잡해지니 "회전" 기능을 제외한 다른 메뉴들은 별도로 바인딩 하지 않는다. 
        self.Bind(wx.EVT_MENU, self.OnRotateL, rotate_l)
        self.Bind(wx.EVT_MENU, self.OnRotateR, rotate_r)



    # Right 회전
    def OnRotateR(self, e):
        fileCtrl = wx.FindWindowById(321)
        # 선택된 파일경로
        path = fileCtrl.GetPaths()[0]
        # png 파일인 경우,
        if path.endswith('.png'):
            # 비트맵 생성
            bmp = wx.Bitmap(wx.Image(path, type=wx.BITMAP_TYPE_PNG).Scale(300, 300).Rotate90(clockwise=True))
            # 비트맵 레이블 할당
            self.frame.sbmp.SetBitmap(bmp)
            # 그림 가운데 표시
            self.frame.sbmp.Center()

    # Left 회전
    def OnRotateL(self, e):
        fileCtrl = wx.FindWindowById(321)
        # 선택된 파일경로
        path = fileCtrl.GetPaths()[0]
        # png 파일인 경우,
        if path.endswith('.png'):
            # 비트맵 생성
            bmp = wx.Bitmap(wx.Image(path, type=wx.BITMAP_TYPE_PNG).Scale(300, 300).Rotate90(clockwise=False))
            # 비트맵 레이블 할당
            self.frame.sbmp.SetBitmap(bmp)
            # 그림 가운데 표시
            self.frame.sbmp.Center()


if __name__=="__main__":
    app = wx.App()
    frame=Example(parent=None, id=-1)
    frame.Show()
    app.MainLoop()

 

 

 

    도움되셨다면 하트(♥) 부탁드리고, 더 궁금한 사항은 댓글로 남겨주세요 :) 

 

반응형