· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
Wxglade-Tutorial

wxGlade - a GUI builder for wxWidgets



주의 : 이 버젼의 튜터리얼은 CVS의 현재버젼에 맞추어져 있으므로 현재의 wxGlade의 릴리즈 버젼과는 차이가 있을 수 있다.

wxGlade Tutorial 이 튜터리얼의 목적은 wxGlade에 대한 전반적인 사항과 기능에 대해 대략적으로 알아보기 위한 것이다. 짧은 내용에도 불구하고, 차근차근히 매뉴바와 상태바 그리고 notebook같은 컨트롤이 포함된 frame을 어떻게 만드는지를 통해서 어떻게 프로그램이 동작하는지에 대해 알 수 있을 것이다.


1. frame 생성

새 프레임을 만들기 위해서는, "팔렛트"에서 적당한(역자주:프레임) 버튼을 클릭한다. 새창에 해당하는 클래스의 이름을 요구하는 창이 뜰것이다. 이름을 입력하되, 반드시 python이나 c++ 클래스에 사용할수 있는(문법적으로 맞는) 이름이어야 한다.

이제 프레임창이 보이고, 속성창이 방금 생성된 widget의 속성을 보여줄것이다. 이제 frame의 제목(해당 오브젝트의 이름과 동일해짐)을 바꾸어 보자. "Frame with notebook" 이라고 입력해 보자. 제목 입력란을 벗어나면 바로 적용되어 질 것이다.

2. 매뉴바 만들기

현재 프레임의 속성창을 선택한다. 그리고 해당 프레임에서 매뉴바 생성을 선택한다.

속성창이 변하며, 매뉴바의 속성을 보여주기 시작한다. : 매뉴 버튼 수정을 클릭하고 매뉴 에디터로 매뉴를 몇개 추가한다.

"add" 버튼을 눌러 매뉴를 추가한다. 그리고 Label 항목을 "File"로 수정한다. 이제 File 매뉴에 하부매뉴를 추가해 보자 : "Add"버틍를 클릭하고, Label항목을 "New"로 바꾼다. 그리고 > 버튼을 클릭한다. : New메뉴가 File메뉴 하부메뉴로 표시되기 위해 안쪽으로 들여쓰기 된것을 볼 수 있다.

3. 상태바 만들기

프래임 속성창(widget 탭)에서 Has MenuBar 아래에 Has StatusBar를 선택한다.

속성창은 현재 상태바의 속성을 나타내고 있다. : 수정하기 위해 더블클릭한다. "Created with wxGlade!"로 수정한다. size 속성은 해당 속성의 차원을 나타낸다. 최소한 하나의 필드는 -1의 값을 가져야 한다.(남은 공간을 모두 채우는 필드이다.)

4. notebook 만들기

이제, 현재 프레임에 notebook을 추가해 보자. 추가하게 되면 현재 프레임이 BoxSizer가 막 추가된것을 볼수 있다. 그 이유는 모든 컨테이너 위젯(container widget)은 하부 위젯(sub-widgets)을 추가하기 위해서는 Sizer를 가지고 있어야 하기 때문이다. 그리고 일반적으로 프레임은 하나의 자식 윈도우를 가지게 되므로 wxGlade는 1-solt BoxSizer를 자동추가 한다.

이제 notebook을 추가한다. 그러기 위해서는 프레임을 선택한후 팔렛트에서 Notebook 버튼을 클릭한다. 그리고 sizer위로 드래그 한다. 그러고 나면 notebook 탭의 위치를 고르는 창이 뜬다. 선택한다.

이제 속성창을 선택해보. 이제 클래스 이름이 wxNoteBook인것을 볼수있다. 다시말해 오브젝트의 클래스 이름이다. 만약 값을 수정하면 wxNotebook 클래스를 상속받은 새로운 클래스를 만들게 된다. 프로그램 동작시에는 아무런 영향이 없으나 새로 생성된 클래스의 정의된 코드를 생성하게 된다 wxGlade가 새로운 클래스를 위한 코드를 생성하도록, 새로 생성된 MyNotebook 클래스의 값을 수정해 보자

주의 : 위의 설명은 소위 "container" widgets 에만 해당된다. 다시 말해 자식을 소유할수 있는 것만 해당된다. contol은 약간 다르다. 예를 들면..

패널안에 버튼을 넣었다. wxButton 클래스를 사용한다. 새로 생성된 MyCustomButton의 어떤 값을 수정하면 wxGlade는 wxButton 클래스를 상속받은 MyCustomButton이 어딘가에 정의 되어있고, 그 클래슨는 일반적인 wxButton 클래스와 호환되는 생성자를 가졌다고 생각하고 그 부분에 대한 코드를 생성한다. 아래가 그 예이다.
 button_1 = MyCustomButton(parent, id, "Label")
instead of
 button_1 = wxButton(parent, id, "Label")

주의 2: XRC 출력에 있어서는 기존의 것과 클래스의 값이 다르면 그 객체가 상속받은 것이라고 생각한다. 위의 예제에 해당하는 출력이 다음과 같다.
 <object class="wxButton" name="button_1" subclass="MyCustomButton"/> 

그러므로 XRC ouput에서 주의할점은 소위 "top-level" widget(frame, dialog, ...)들을 추가할때 클래스값을 초기치로 리셋해야 함을 기억해야한다. 그 이유는 wxGlade는 상속된 클래스로 인식하기 때문이다.

5. notebook page 추가, 삭제 하기

이 동작은 statusbar의 필드를 다루는것과 거의 동일하다. notebook control의 탭 속성은 페이지의 값과 그 제목을 설정한다.("Apply" 하는것을 잊지 말라!)

6. 컨트롤 추가하기.

이제 이 짧은 tutorial의 마지막 파트에 도달했다. : notebook의 첫페이지에 몇몇 컨트롤을 추가해 보자. text area 와 두개의 버튼을 추가할 것이다. 이 동작들은 sizer들을 이용해서 객체들을 layout하는것과 wxGlade의 cut & paste 지원을 보게 된다.

전에 얘기했듯이 container안에 widgets을 추가하기 위해서는 sizer를 이용해야 한다. 이제 콘트롤들이 추가될 notebook의 첫페이지에 sizer를 추가해 보자. 이제 팔렛에서 BoxSizer 버튼을 클릭한다. 마우스를 페이지 안으로 이동시키면 포인터가 십자모양이 된다. 그리고 페이지에 sizer를 떨어뜨린다. 이제 추가할 sizer에 대한 몇가지 속성을 묻는 창이 뜰것이다. 현재값을 수정한다. 2칸짜리 vertical box로 만든다. 이것은 강제조항은 아니다. sizer의 칸수는 언제든 바뀔수 있다. 전자는 클래스 속성을 수정하는 것이고, 후자는 sizer의 "handle"버튼 위에서 우클릭 하거나 widget 트리에서 해당 노드를 통해서 팝업메뉴를 띄울 수 있다. (다시말해. wxGlade에서는 거의 모든 객체에 대한 메뉴를 이런식으로 띄울수 있다.)

TextCtrl 버튼을 클릭한후에 sizer의 첫번째 슬롯에 넣어보자. 기본정렬은 오른쪽정렬이다. layout을 수정하기 위해서는 TextCtrl의 layout속성탭을 선택한다. Alignment의 wxEXPAND 값을 1로 수정한다. 여러줄을 출력하고 싶으면 Style(Widget 탭에서)의 wxTE_MULTILINE 의 체크박스를 체크한다. : wxGlade에서는 대부분의 Style 속성의 수정은 바로 보이지는 않지만 생성된 코드에는 적용이 된다.

두번째 슬롯에 horizontal Sizer을 배치한다. 여기는 버튼이 두개 들어간다. 슬롯의 숫자는 3으로 수정한다. 두 버튼 사이에 공간을 주기 위한 것이다. (화면에서 둘 사이가 너무 붙게 하지 않기 위해서이다.)

첫번째 슬롯에 적당한 버튼을 새로 넣는다. 두번째 버튼을 추가하기 위해서 클립보드를 사용할 것이다. 첫번째 버튼의 팝업메뉴에서 Copy item을 클릭한다.(아니면 그저 버튼을 선택한 후 Ctrl+C를 누른다.), 이제 마우스를 세번째 슬롯에서 슬롯에 팝업메뉴에서 복사된 widget을 붙이기 위해 Paste item을 클릭한다.(아니면, 빈 세번째 슬롯을 선택한 후 Ctrl+V를 누루거나, 빈 세번째 슬롯에서 마우스 버튼이 3개라면 가운데 버튼을 누르면 된다.)

적당한 거리를 유지하기 위해, 이제 두 버튼 사이에 spacer를 추가한다.

이제 마지막으로 버튼이 들어있는 horizontal Sizer의 속성에서 wxEXPAND값을 0으로 수정하고, wxALIGN_CENTER_HORIZONTAL을 체크하고, 버튼을 text area와 아래쪽 notebook으로 부터 분리하기 위해 위쪽(wxTOP)과 아래쪽(wxBOTTOM)의 border값을 4로 수정한다.


NOTE on widgets' ids: 모든 wxWindows widget은 event handling등에서 사용 되어지는 id값을 가지고 있다. 그러므로 wxGlade의 각 widget은 id 속성을 가지고 있다. 그 값은 다음과 같은 값들이 올 수 있다.

  • a number: widget의 생성자로 부터 얻어진 integer값이다.
  • a name: 이 경우 wxGlade는 프로그램 어딘가에 선언된 id의 이름으로 생각하고 사용한다. 예를 들면 "wxID_OK"을 dialog의 기본 OK 버튼의 id값으로 사용할 수 있다.
  • a pair name=value: 이 경우 widget의 생성자가 변수를 생성하기 전에 사용할 수 있다. 예를 들면 "Test" 버튼의 id로 TEST_BUTTON=wxNewId()을 사용할 수 있다.(C++ 코드 생성규칙에 의하면 : constant initializer에 의해 생성된 id값이 anonymous enum으로 저장된다. 그러므로 이 경우의 할당은 규칙에 어긋나지만 - 임시로 TEST_BUTTON=100과 같이 사용할수 있다.)
  • a pair name=?:이런 특이한 형태는 코드가 "name"에 해당하는 선언부를 가지게 된다. 자동으로 unique id가 할당된다. 파이썬에서 "name=wxNewId()"과 동일한 형태이다. C++에서는 "name=1000"과 동일한 표현이다.( 물론 1000은 단지 예를 든것이다.) 후자의 경우 wxGlade는 는 정확하게 id값을 1000으로 값을 정하려고 할것이다. 목적에 따라 id값을 정하면 되겠다.

7. Last changes


마지막으로, 현재 layout이 맘에 들지 않으면, 버튼들을 test area 아래가 아니라 위에 둘 수도 있다.어떻게 하는가? 간단하다. : 버튼들이 들어있는 Sizer의 Pos속성을 수정한다. test area 이전에 sizer를 두기 위해 값을 0으로 수정한다. 쉽지 않은가?

Now our window is complete: all we have to do is set a reasonable initial size for it. To do this, resize the frame until you find a good size, and then activate the Size property.

8. Code generation

코드 생성 이전에 저장하자. main wxGlade 윈도우의 File menu에서 Save As... 을 선택한다.반드시 필요한 작업은 아니지만 위험요소를 줄이는 아주 좋은 공부다. 아직 wxGlade는 아직 그 정도로 프로그램이 성숙해 있지는 않다. :-)

이제 code를 생성해 보자 : tree widget에서 Application 항목을 선택하자(맨위에 있다.) 속성창에 Application탭이 보인다. 이 패널은 code generation 옵션을 가지고 있다.

  • Name: wxApp Object의 이름을 설정한다. 이것은 프로그램의 이름이 된다. 만약 이 속성과 다음 속성(Class)이 활성화가 안되어 있다면, 그 이유는 appication startup에 대한 코드가 없는 것이다. 그러나 이것은 몇몇 widget에만 해당된다.

  • Class: wxApp로 부터 상속된 클래스의 이름이다. 이 속성과 이전 속성(Name)이 활성화가 안되어 있다면 application 객체가 wxPySimpleApp일 것이다.(이 것은 Python언어에만 해당된다. C++의 경우는 startup 코드가 생성되게 하려면 반드시 활성화가 되어 있어야 한다.)
  • Encoding: 저장할 .wxg(또는 XRC) 파일에서 사용될 encoding 이다.
  • Enable gettext support: 만약 체크되면, 생성된 소스코드의 모든 문자열은 "_()"로 추가된 형태로 수정될 것이다. 이것은 gettext를 위한 것이다.
  • Top window: 생성될 프로그램의 주 윈도우
  • Code generation: 출력에 해당하는 사항을 조절한다. 모든 widget을 포함하는 하나의 소스파일을 만들것인지, 각 클래스가 정의된 따로따로 파일로 만들것인지(C++용으로 출력할때는 ".h" 과 ".cpp" 두개의 파일을 생성한다.) 정한다.
  • Language: 어떤 언어(Python, C++, XRC(wxWindows 자원저장용 xml 포맷))로 코드를 생성할지 정한다. 마지막 경우 application의 몇몇 속성(Name, Class, Top window)을 무시한다. 그리고 몇몇은 비활성화된다. (여러 파일에 코드생성이 불가능하다.)
  • Overwrite existing sources: 만약 체크되면, 코드 전체가 업데이트 되지 않고 다시 생성된다.(자세한 내용은 아래의 첫번째 note를 참고한다.)
  • Output path: 단일 파일 모드일 경우, 생성할 파일 이름이다. 여러개 파일로 생성할 경우, 출력할 디렉토리 명이다. : 마지막 경우, 모든 Custom 클래스는 각 Class의 이름으로 파일이 생성된다. 단 wxApp 클래스는 예외이다. 위에서 설명한 Name 속성값으로 생성된다. 예를 들면 notebook의 경우 MyFrame.py, MyNotebook.py, app.py(Python 일 경우)
  • Generate code: 코드 생성 시작 버튼
위에서 설명한 옵션들을 선택한후 Generate code버튼을 누르면, 잠시 후 메시지 동작이 끝났다는 메시지 창이 뜨고 코드 생성이 끝이 난다. 마치 이 짧은 tutorial처럼.. ;-)

9. Notes

이번엔 wxGlade에 대해 반드시 알아야 할 것들에 대해 알아보자.(알려진 버그, 한계, 숨겨진 기능, tips and tricks...) tutorial에서 다루지 못했던.. 중요성에 따라 대충 정렬해 보았다..

Python 또는 C++ code를 생성할 때, 출력 파일이 존재하면, wxGlade는 기본적으로 모든 내용을 저장하지 않고, 아래의 코드 사이의 내용만 저장한다.
  # begin wxGlade: ...
  # end wxGlade
 
GUI코드를 다시 생성할경우, 이 기능은 대부분의 경우 임의로 저장한 코드를 잃을 걱정을 하지 않고 작업할 수 있게 해 준다. 그러나 주의할 점이 있는데 다음과 같은 사항을 주의 해야 한다.
  • 만약 출력할 파일에 custom 클래스중 같은 이름의 클래스가 있을 경우, 그리고 wxGlade 블럭이 없는경우, 그 클래스에 대한 코드는 생성되지 않는다.(shell에서 경고 메시지는 출력된다.)
  • 만약 custom classes 중 이름이 변경하면, 생성된 파일의 것도 같이 수정되어야 한다. (그리고 wxGlade tags의 이름도 같이 수정되어야 한다.) 그 이유는 wxGlade가 수정되기 이전의 이름을 알 방법이 없기 때문이다. 그리고 완전히 새로운 것으로 인식된다. (다시말해 기존의 것을 수정하는 것이 아니라 새로 생성된 클래스로 인식하고 생성해 버린다.) 예를 들면 MyFrame이라는 클래스가 있고, 생성된 파일은 frame.py이다.
    #!/usr/bin/env python
    # generated by wxGlade 0.2 on Sat Dec 14 15:15:06 2002

    from wxPython.wx import *

    class MyFrame(wxFrame):
        def __init__(self, *args, **kwds):
            # begin wxGlade: MyFrame.__init__
            kwds["style"] = wxDEFAULT_FRAME_STYLE
            wxFrame.__init__(self, *args, **kwds)

            self.__set_properties()
            self.__do_layout()
            # end wxGlade

        def __set_properties(self):
            # begin wxGlade: MyFrame.__set_properties
            self.SetTitle("frame_1")
            # end wxGlade

        def __do_layout(self):
            # begin wxGlade: MyFrame.__do_layout
            pass
            # end wxGlade

    # end of class MyFrame
      


    이제 MyFrame을 RenamedFrame으로 이름을 변경하면, 만약 frame.py을 수정하지 않는다면, 그리고 코드를 다시 생성시킨다면 다음과 같은 결과가 나타난다.
    #!/usr/bin/env python
    # generated by wxGlade 0.2 on Sat Dec 14 15:15:06 2002

    from wxPython.wx import *

    class RenamedFrame(wxFrame):
        def __init__(self, *args, **kwds):
            # begin wxGlade: RenamedFrame.__init__
            kwds["style"] = wxDEFAULT_FRAME_STYLE
            wxFrame.__init__(self, *args, **kwds)

            self.__set_properties()
            self.__do_layout()
            # end wxGlade

        def __set_properties(self):
            # begin wxGlade: RenamedFrame.__set_properties
            self.SetTitle("frame_1")
            # end wxGlade

        def __do_layout(self):
            # begin wxGlade: RenamedFrame.__do_layout
            pass
            # end wxGlade

    # end of class RenamedFrame


    class MyFrame(wxFrame):
        def __init__(self, *args, **kwds):
            # content of this block not found: did you rename this class?
            pass

        def __set_properties(self):
            # content of this block not found: did you rename this class?
            pass

        def __do_layout(self):
            # content of this block not found: did you rename this class?
            pass

    # end of class MyFrame
      


    이것은 명백히 원하던 동작이 아니다..
  • 만약 wxg 파일의 custom 클래스를 제거하면, wxGlade는소스코드를 재생성할때ㅤㄸㅒㅤ자동으로 소스코드에서도 제거한다. (이전버젼의 소스가 없다면 당연히 적용 안된다.), 그러나 wxGlade 블럭내의 코드를 업데이트 하려고 할것이다. 이 의미는 다음과 같다.
    • If you want to remove the class, you have to do it manually,
    • 만약 이 클래스를 제거하기를 원한다면, 수동으로 해야할 것이다.
    • If you want to keep the class as is, you have to remove the wxGlade tags.
    • 만약 이 클래스를 유지하기를 원하면, wxGlade tags를 제거해야 한다.
0.3버전에서는 Application 속성중 "Overwrite existing sources"을 체크함으로서 "update contents" 기능을 끄는 것이 가능하다. 만약 체크 되어 있으면 wxGlade는 코드를 밑바닥부터 다시 생성한다. (View->Preferences->Others에서 적당한 백업기능을 수행하게 할 수 있다.)

  • 프로그램에 새로운 클래스를 추가할 때 만약 이전에 생성된 코드가 있다면, 새 클래스의 선언부는 이전 코드에 추가되지는 않을 것이다. 이것은 대체적으로 문제는 안된다. 그러나 C++ 출력에서는 컴파일 되지 않을 수 있다. "out of box", 그러므로 직접 몇가지 코드 수정을 해 주어야 한다. (e.g. 새 클래스 이전에 몇가지 선언을 해준다.)
  • sizer에 slot을 추가할때 새로운 슬롯이 보이지 않을 수 있다. 이것은 sizer를 갖고 있는 window의 사이즈가 너무 작을때 일어날 수 있다. 그러므로 사이즈를 재조정하면 해결된다. layout이 다시 조정되고 새로운 slot이 보여진다.
  • XRC 코드 생성은 Python이나 C++과 몇가지 다른 점이 있다. section 8에서 다루었던것과 달리 중요한 점은..
    • 일부 widgets이 전혀 지원되지 않는다.(e.g. status bar 와 gird): 이 코드들은 생성되지 않는다. 대신에 XRC output 파일은 다음과 같은 comment를 포함하고 있다.
      <!-- code generator for wxStatusBar objects not available -->
        

    • Output 파일들은 항상 덮어씌워진다. 그러므로 직접 XRC 파일을 수정하면 코드를 재생성할때 직접 수정한 것들은 모두 사라진다.
    • 02.버젼 이후로 CustomWidget()이라는 특별한 컴포넌트가 있다. 다른점은 wxg 파일안의 어떤 widget에서는 쓰일수 있다.wxGlade가 지원하지 직접 지원하지 않는 것에서도 쓰일 수 있다. 가장 중요한 기능은 Argument 속성이다. 이것은 Python 또는 C++ 에 대해 두가지 다른 의미가 있다. 객체에 대해 생성자 parameter를 정의할수 있다. 이경우 두개의 특별한 parameter는 $parent 과 $id 이다. 이것은 그 객체의 실제 id와 부모로부터 그들의 이름과 저장소를 추측할 수 있다. XRC에 대해서는 특별한 추가 속성이 있다. 이경우 폼에서 다음과 같다.
  • name: value
     
    (invalid entries will be silently ignored): for each of these lines, the output will contain a
    <name>value</name>
     
    property of the XRC object.
  • 0.2 버젼 부터는 wxGlade는 xrc2wxg.py라는 스크립트를 제공한다. 이것으로 XRC 파일을 wxGlade 파일로 변환할 수 있다. 그러면 wxGlade에서 수정할 수 있다. 사용법은 다음과 같다.
    python xrc2wxg.py xrc_file.xrc wxg_file.wxg
     
    (만약 wxg_file.wxg가 생략되면 기본값으로 xrc_file.wxg가 된다.), 그러나 이것은 몇가지 제한을 두고 있다.. 알아보자.
    • 우선, 이것은 "wxGlade-friendly(wxGlade 호환)" XRC 파일들만 다룰 수 있다. 이것은 기본적으로 모든 윈도우 최상위 윈도우 빼고, 반드시 sizer안에 존재하여야 한다는 것이다. (예외는 있다.)
    • wxGlade가 모르는 모든 widget은 반드시 특별한 CustomWidget 컴포넌트로 대체되어야 한다.
    • 마지막으로 xrc2wxg는 기본적으로 시험판이다. 그러므로 버그가 있을 수 있다. 만약에 발견되면 보고하라(this is valid for wxGlade in general, BTW).
  • 코드 생성기능을 GUI를 띄우지 않고 command line에서 행할 수 있다. 쉘상에서 다음과 같이 한다.
    python wxglade.py -h
     
    at your shell's prompt.

이 내용이 알기 쉽기를 바란다.. 나의 영어는 다소 미흡하다. 어째든 질문, comment, 비평은 e-mail을 통할 수 있다. agriggio <at> users <dot> sf <dot> net.


Alberto Griggio


번역 : 심승준, dwYoon안


dwYoon님 정리해 주셔서 감사합니다.

ID
Password
Join
Among the lucky, you are the chosen one.


sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2006-06-04 22:23:21
Processing time 0.0137 sec