2011년 6월 9일 목요일

GTK+와 Glade3 GUI 프로그래밍 도움글 - Part 1

-출처 : http://www.micahcarrick.com/12-24-2007/gtk-glade-tutorial-part-1.html#Getting_Familiar_with_the_Glade

GTK+ 와 Glade3 GUI 프로그래밍 도움글 - Part 1


December 24th, 2007

Glade3를 이용한 User Interface 디자인하기



GTK+와 Glade3 GUI 프로그래밍 도움글 연재 Part 1 에서, 우리는 아래의 그림에서 보는 것과 같이 GTK+ text editor를 위한 graphical user interface(GUI)를 디자인 할게 될 것이다. 이것은 앞으로 하게 될 모든 도움글에서 사용하게 될 것이다. 이러한 GUI 디자인은 Glade Interface Designer를 사용해서 만들 것이고, 뒤에 설명할 도움글에서 소개될 디자인을 구현하는데 사용할 프로그래밍 언어와는 철저히 독립된 것이다.


GTK+와 Glade3 GUI 프로그래밍 도움글 목차

  1. Part1 - Glade3를 이용한 User Interface 디자인 하기
    1. GTK+ 개념의 간단한 개요
    2. Glade3의 소개
    3. Glade interface와 친숙해 지기
    4. Widget의 속성 다루기
    5. Signal을 위한 Callback함수 지정하기
    6. GtkWindow에 Widget 더하기
    7. Packing 방법에 따른 모양새의 효과
    8. Menu (혹은 Toolbar) 편집하기
    9. 주 Window 마지막 손질하기
    10. Glade를 사용하는데 필요한 추가 도움 얻기
    11. 다음 것들...

  2. Part2 - GTK+ 개발을 위한 프로그래밍 언어 선택하기
    1. 가장 좋은 언어는 ?
    2. 언어 선택에 고려해야할 것들
    3. Python과 C 언어 비교해서 살펴보기
    4. 다음 것들..

  3. Part3 - Glade 파일을 실행하는 기본적인 프로그램 작성하기
    1. 개발환경 구성하기
    2. GtkBuilder와 LibGlade
    3. 가장 간단한 application
    4. application 컴파일 하고 실행하기
    5. 코딩으로 넘어가기
    6. 다음 것들...

GTK+ 개념의 간단한 소개

여러분들이 GTK+를 경험해 본 적이 없다면, 내가 소개할 개념 중 약간은 어려울 수 도 있습니다. 그때 그때 이러한 개념들을 설명하려 하겠지만, 이 도움글의 part 1을 거친 후에는 아마도 이러한 아이디어를 좀 더 잘 숙달하게 될 것이다. GTK+의 기본적인 개념에 대한 이해는 효과적으로 Glade를 사용할 수 있는 능력에 도움이 될 것이다.

무엇보다도, GTK+는 프로그래밍 언어가 아니다. GTK+는 개발자가 Linux, OSX, Windows 그리고 GTK+를 사용 가능한 Platform을 위한 GUI application을 개발하는데 사용하는 라이브러리의 모음집이나 툴킷이다. Windows에서 사용하는 Win32 API이나 MFC, Java에서 사용하는 Swing과 SWT, KDE에서 사용되는 Linux의 GUI 툴킷인 Qt와 같은 개념으로 생각 할 수 있다.

비록 GTK+자체는 C로 쓰여 졌지만, C++, Python, Perl, PHP, Ruby, 나 많은 다른 언어로의  "binding"을 제공하여 GTK+ application을 프로그래머가 개발 할 수 있도록 해준다.

GTK+ 는 크게 Glib, Pango, ATK의 라이브러리에 기초한다. 그리나, 우리는 주로 GTK+만 가지고 작업하고, GTK+와 이들 3개의 라이브러리와의 상호작용은 신경쓰지 않을 것이다. GLib는 호환성을 위한(여러분의 코드가 Windows와 Linux에서 실행할 수 있도록) 표준 C 라이브러리 함수들을 포함하고 있다. 우리는 C나 C++로 작업할 때 대부분 GLib를 사용한다. C를 사용해서 우리의 디자인을 구현할 때는 좀 더 철저하게 설명할 것이다. Python이나 Ruby같은 Higher-level 언어들은 비슷한 기능을 제공하는 자체 표준 라이브러리를 가지고 있기 때문에 GLib에 관해서 걱정할 필요없다.

GTK+와 그와 관계된 라이브러리들은 GObject를 통한 객체지향접근(object oriented approach)을 구현한다. 이게 어떻게 가능한지는 아직 중요하지 않다. 그리고 프로그래밍 언어의 종류에 따라 이러한 점을 여러분에게 다른 형태로 드러낼 것이다. 하지만, GTK+는 객체지향을 사용하고 있다는 것을 이해하는 것은 중요하다. (C언어에서도 마찬가지이다.)

GTK+ GUI의 모든 부분들은 하나의 객체(object)인 "widgets"가 하나 혹은 그 이상이 모여진 것이다. 모든 widget들은 GtkWidget이라는 기초 widget으로부터 유도되어진 것이다. 예를 들면, 응용프로그램의 윈도우는 GtkWindow라는 widget이다. 그리고 그 윈도우에 있는 툴바는 GtkToolbar라는 widget이다. 비록 GtkWindow도 GtkWidget이지만, GtkWidget은 본질적으로 GtkWindow와 다르다. 자식 widget들은 객체에 기능이 확장하기 위해 부모 widget으로 부터 유도되어 진다. 이러한 개념은 전형적인 OOP(object oriented programming) 개념이다. (이것이 새로운 개념이라면 "object oriented programming"으로 구글링해 보아라)

우리는 어떤 객체로부터 유도되어진건지 보기 위해서 GTK+ reference 문서에서 어떤 widget이던지볼 수 있다. GtkWindow의 경우는 아래와 같다.

  GObject  
   +----GInitiallyUnowned  
      +----GtkObject  
         +----GtkWidget  
            +----GtkContainer  
               +----GtkBin  
                  +----GtkWindow  

여러분들이 보듯이, GtkWindow는 GtkContainer로 부터 유도되어진 GtkBin으로 부터 유도되어졌다. 여러분의 첫 application을 위해서, GtkWidge 객체 상위의 것들에 대해서 걱정할 필요는 없다. 이러한 계층구조가 중요한 이유는 여러분들이 어떤 특정 widget의 기능과 속성, 그리고 signal들을 알려고 할때, 그 부모 객체에도 적용되는 기능과, 속성, 그리고 signal들을 알아둘 필요가 있기 때문이다. part 2에서 example application에 대한 코드를 작성할 때 이러한 것들이 더 표면적으로 나타나게 될 것이다.

우리는 또한 이름짓기에 유용한 표현들을 살펴볼 것이다. 이건 아주 다루기 쉽다. 우리는 객체와 함수가 어떤 라이브러리로부터 왔는지 쉽게 말 할 수 있다. Gtk라는 첫 문자로 시작하는 모든 객체들은 GTK+로부터 온 것이다. 나중에, 우리는 Glib의 한 부분인 GError나 Libglade의 한 부분인 GladeXML같은 것을 볼 것이다. 모든 객체들의 이름은 camel case(하나 혹은 그 이상의 문자를 조합하여 이름을 짓는 방법으로 낙타의 등 모양의 문자 형태를 띈다. GtkWidget...같이)의 형태를 띈다. 이러한 객체들을 다루는 함수들의 이름은 자간에 '_'를 사용하는 소문자로 이루어진다. 예를 들면, gtk_window_set_title()은 GtkWindow 객체의 타이틀 속성을 설정하는 함수이다.

여러분이 필요로 하는 모든 reference 문서들은 library.gnome.org/devel/references 에 있다. 그러나, 여러분의 배포에 용이한 패키지로 제공되는 Devhelp가 더 사용하기 쉽다. Devhelp는 여러분들이 (여러분이 라이브러리 문서들도 설치하였다고 가정한다면) 시스템에 설치된 라이브러리를 위한 API 문서를 검색 및 훌터 볼 수 있도록 해준다.

GTK+와 Glib에 대한 더 많은 정보:

Glade3 소개

Glade 는 GTK+ 응용프로그램을 디자인하기 위한 RAD(Rapid Application Development)툴이다. Glade 는 GTK+ 응용프로그램 자체이기도 하다. 간단히 말해서 응용프로그램의 인터페이스를 구현하는 과정을 단순화 하는데 개발자가 사용하는 소프트웨어의 한 조각이다. Glade는 "glade file"로 참조되기 위해 hereforth(?)하는 어떤 것을 생성한다. glade file은 실제로 인터페이스를 구성하는 widget들의 계층도를 설명하는 XML파일이다.

Gloade는 처음에 GUI를 만드는 C코드를 생성했었다.(아직도 이러한 작업을 하는 도움글과 예제를 찾아 볼 수 있다.) 나중에 이것은 실행 시 인터페이스를 만들때 사용하는 라이브러, Libglade의 특성에 방해를 받았다. 그리고 결국 Glade3의 등장으로 이러한 오래된 방법은 비난받게 되었다. 이건 단지 GUI가 어떻게 생성되어져야 하는지를 설명하는 glade file을 만들도록 허용하는 것을 의미한다. 이러한 것은 작은 인터페이스 변화가 필요할 때 제 컴파일하지 않아도 되도록 개발자에게 유연성을 제공한다. 그리고 더 많은 프로그래밍 언어들이 Glade를 사용하도록 허용한다.

Glade3는 Glade2같은 이전 버전에서 중요한 차이점을 가진다. Glade3를 다운받는 작업은 아주 잠시동안에 이루어져야하고, 여러분들은 그것을 구하는데 어떠한 어려움도 가지지 말아야한다. 여러분들에게 패포하기 위한 패키지 관리자(yum, aptitude, etc)는 Glade3를 사용가능으로 해야한다. 하지만, 여러분은 패키지는 안에 3개가 포함되어 있다는 것을 유념해야한다. glade라는 이름은 오래된 패키지의 이름이고, 'glade-3' 나 'glade3'는 이 도움글의 바탕이되는 새로운 버전에 대한 패키지 이름이다. Glade의 소스코드는 glade.gnome.org 에 있다.

Glade 인터페이스와 친숙해 지기

Glade를 시작하고 그 인터페이스와 친숙하게 되어 보자. 나는 여기에 언급된 이름들로 Glade의 다양한 측면들을 참조할 것이다. 왼쪽 측면은 "Palette"다. Palette는 그래픽 편집 프로그램에서 사용하는 것과 같다. 이건 응용프로그램을 디자인할 때 사용할 수 있는 GtkWidget의 팔레트이다. 중간 영역(Glade를 처음 실행할 때는 비워져있다)에는 "Editor"라는 곳이 있다. 이곳은 진행상황에 따라 디자인을 확인해 볼 수 있다. 오른쪽 측면은 윗쪽에는 "Inspector", 그 아래쪽에는 widget의 "Properties" 으로 구성되어져 있다. Inspector는 여러분의 디자인을 이루는 widget들의 계층구조를 보고 확인할 수 있도록 트리구조로 보여준다. 우리는 signals을 다루는 callback 함수를 기입하는 작업을 포함한 widget의 다양한 속성을 Properties 탭에서 다룰 수 있다.

그래서, 우리가 해야 할 가장 첫 번째 것은 Toplevel widget을 만들고 저장하는 작업이다. 이 작업은 'Toplevels'셕션 아래 Palette에 있는 GtkWindow 아이콘을 클릭하면 된다. 그럼 여러분은 Glade의 Edit영역 안에 생성되는 회색 박스가 생성되는 것을 확인 할 수 있다. 이 부분이 GtkWindow의 작업 영역이다. 제목 바, 닫음 버튼, 등등의 것들이 수정하는 동안에는 볼 수 없지만 window manager (GNOME 같은 것)에 의해서 widget에 추가될 것이다. 우리는 매번 Glade에서 GtkWindow라는 toplevel widget에서 작업을 시작하게 될 것이다.

자, 앞으로 더 진행하기 이전에 지금의 상황을 "tutorial.glade"라는 파일로 저장하도록 하자.


그럼 여러분이 저장한 파일 "tutorial.glade"를 살펴보면 XML 파일이라는 것을 확인해 볼 수 있을 것이다. 텍스트 에디터로 열어 보면 다음과 같이 보여질 것이다.

 <?xml version="1.0" encoding="UTF-8" standalone="no"?>  
 <!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">  
 <!--Generated with glade3 3.4.0 on Tue Nov 20 14:05:37 2007 -->  
 <glade-interface>  
  <widget class="GtkWindow" id="window1">  
   <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>  
   <child>  
    <placeholder/>  
   </child>  
  </widget>  
 </glade-interface>  

보는 봐와 같이, 그저 단순한 XML파일이다. part 2에서 우리는 실행 단계에서 UI를 구성하고, 이 XML파일을 분석하기 위해 Libglade를 C언어에서 불러다 사용할 것 이다. XML 의 경우는 Python이나 기타 다른 프로그램 언어에 의해서 쉽게 분석될 수 있다. 우리는 Glade를 가지고 작업을 진행함에 따라서, 이 파일은 XML 형식으로 우리의 인터페이스를 묘사하는 정보들로 채워질 것이다. 자 그럼, 텍스트 에디터를 나가서 다시 Glade로 돌아 가자.

Widget의 속성 다루기

Glade 의 Editor는 지금 빈 GtkWindow widget을 보여주고 있다. 우리는 widget의 속성 중 한 부분을 다루게 될 것이다. 여러분이 만약 Glade의 Properties 판을 보고 있다면, 4개의 탭을 볼 수 있을 것이다. 'General', 'Packing', 'Common', 그리고 'Signals'. 앞의 2개 부터 이야기해 보기로 하자. GtkWidget들은 통상적으로 화면에 어떻게 출력되고 어떠한 기능을 해야하는 다양한 속성들을 가지고 있다.

만약 여러분이 reference documentation for a GtkWidget 에 가서 Properties 셕센을 살펴 본다면, GtkWindow의 속성 리스트를 볼 수 있을 것이다. 이것들은 widget에 따라 차이가 있지만 통상적으로 Glade의 properties 패널의 'General'탭에 나타나는 속성들이다. name 속성은 Glade에서 모든 widget이 다가지고 있고, application을 위한 코드를 작성해야하는 시기가 되었을때 widget을 참조하기 위해 사용하게 될 것이다. GtkWindow의 name 속성을 "window1"에서 "window"로 바꾸자. 그리고 나서 'Window Title' 속성에 "GTK+ Text Editor"라고 추가하자.


우리는 'Packing'탭에 대해서 약간 다루게 될 것이다. 하지만 먼저, 'Common'탭을 살펴보도록 하자. 이 탭은 우리의 GtkWindow에 속하는 속성들도 포함한다. 그러나 우리는 GtkWindow에 대한 참조 문서에서 이러한 것들을 찾아 볼 수 없다. 이건 부모 객체로부터 상속된 속성들을 설정하는 곳이기 때문에 생기는 차이다. reference documentation for a GtkWidget 문서의 "Object Hierarchy"색션을 보자. 그럼 여러분은 GtkWindow가 다루어지는 객체를 볼 수 있을 것이다. GtkContainer 링크를 클릭해서 reference documentation for a GtkContainer 로 넘어 가보자. 여러분은 GtkContainer가 "border-width"하는 속성이 Glade에서 'Common' 탭 바닥에 "Border width"로 표현되는 속성이라는 것에 유의 하자. 우리는 나중에 container widget 무엇을 하는 것인 살펴볼 것이다. 그러나,이것은 Object Hierarchy가 얼마나 중요한 지를 보여준다. GtkContainer로 부터 유도된 많은 widgets들에 대해서 Glade는 그것의 속성을 'Common' 탭에 놓아 두었다.

reference documentation for a GtkContainer 의 "Object Hierarchy" 색션에서 여러분은 GtkWidget으로 부터 유도 되었다는 것을 살펴 볼 수 있을 것이다. 그럼 GtkWidget을 클릭해서 reference documentation for a GtkWidget 를 살펴보자. GtkWidget은 Glade의 Properties 판넬에 보이는 많은 것들에 해당하는 많은 속성들을 가지고 있다. 이것들은 GTK+ widget들이 GtkWidget으로 부터 유도되었기 때문에 GTK+ widget들이 가지는 공통된 속성들이다.

Signal을 다루는 Callback 함수 설정하기

객체들은 프로그래머에게 유용한 어떤 작업이 발생할 때 "signal"을 내뿜는다. 이건 Visual Basic 에서의 "events"와 유사하다. 사용자가 여러분의 GUI를 가지고 어떠한 작업을 한다면, 객체들이 signal들을 내뿜을 상황이 된다. 프로그래머 입장에서는 얻어올 signal을 선택하고 작업을 수행하는 callback 함수를 signal과 연결해야 한다.

우리가 배울 첫 번째 signal은 여러분이 만드는 모든 GTK+ application들에 의해서 사용하는 GtkObject가 제공하는 "destroy"이다. 이 signal은 GtkObject가 파괴될 때 내뿜는다. 사용자가 타이틀바의 'x'를 통해서 window를 닫을 때, widget이 파괴되기 때문에 이것은 중요하다. 우리는 이 signal을 잡아서 application이 적절히 종료하기를 원한다. 이러한 작업은 GUI를 위한 코드를 작성할 때 좀 더 명확해 진다. 그러나 지금은 GtkWindow가 "destroy" signal을 내뿜을 때 실행되기 원하는 함수를 설정하는 작업만 하도록 하자.

Glade의 Properties 패널의 'Signal' 탭을 살펴보자. GtkWindow와 이로부터 파생된 각각의 객체가 나열된 곳의 tree 뷰를 보자. GtkObject를 확장하면, GtkObject가 내뿜는 signal들 모두를 볼 수 있다. 이것에 관한 부분은 the reference documentation for a GtkObject 의 "Signal" 색션을 보기 바란다.

'Handler' 컬럼 아래에 편집하기 위해서 ""라는 문자를 클릭하자. 펼침 메뉴에서'on_window_destroy'를 선택하고 ENTER를 치자. 여기에 우리가 원하는 어떤것도 넣을 수 있지만, Glade는 편리한 이름짓기를 위해서 공통적으로 많이 사용하는 callback 함수의 이름을 drop down 메뉴에 제공하고 있다. 이 값은 이 코드에서 어떻게 프로그래머에 의해서 signal과 연결될것인가? 이 도움글에서 우리는 GtkWindow의 "destory" signal이 "on_window_destroy"문자를 갖는 다룸자와 관계되길 원한다. Part 2에서 좀더 자세히 다루어 보자.


여기서, 우리는 실제적으로 GUI 작업을 하고 있고 있지만, 우리의 빈 window를 보여주고 타이틀 바의 'x'를 클릭했을 때 적절히 종료될 수 있도록 하는 기능을 하는 약간의 코드를 C, Python, Ruby, 기타 다른 언어로 작성해야 한다. 이러한 도움글을 위해서 나는 어떤 코드를 작성하기 이전에 Glade3에서의 전체 GUI를 어떻게 작성해야하는 지를 보여줄 것이다. 그러나 호기심 충족을 위해서, 간단한 프로그램이 어떻게 Glade 인터페이스를 구현해서 보여지는지 보기 원한다면 ...

C언어에서,

 /*  
 First run tutorial.glade through gtk-builder-convert with this command:  
  gtk-builder-convert tutorial.glade tutorial.xml  
 Then save this file as main.c and compile it using this command  
 (those are backticks, not single quotes):  
  gcc -Wall -g -o tutorial main.c `pkg-config --cflags --libs gtk+-2.0` -export-dynamic  
 Then execute it using:  
  ./tutorial  
 */  
 #include <gtk/gtk.h>  
 void   
 on_window_destroy (GtkObject *object, gpointer user_data)  
 {  
   gtk_main_quit ();  
 }  
 int  
 main (int argc, char *argv[])  
 {  
   GtkBuilder   *builder;   
   GtkWidget    *window;  
   gtk_init (&argc, &argv);  
   builder = gtk_builder_new ();  
   gtk_builder_add_from_file (builder, "tutorial.xml", NULL);  
   window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));  
   gtk_builder_connect_signals (builder, NULL);  
   g_object_unref (G_OBJECT (builder));  
   gtk_widget_show (window);          
   gtk_main ();  
   return 0;  
 }  

주의 사항 : 컴파일 방법은 파일 이름을 main.c로 저장한 다음과 같이 하시면 됩니다.
gcc -Wall -g -o tutorial main.c `pkg-config --cflags --libs gtk+-2.0` -export-dynamic
 여기서 -export-dynamic을 사용하지 않으면 GTK Warning이라는 메시지를 내보내면서 종료시 연결될 콜백함수를 찾을 수 없다고 알려줍니다. 비슷한 옵션으로 -rdynamic이라는 옵션을 사용해도 무방한데 둘 간의 차이는 아직 찾아 보질 못했습니다.


Python 언어에서 (주의:Glade의 'Common' 속성 탭에서 'window'의 'visible' 속성을 "Yest"로 설정해야한다.)

 #!/usr/bin/env python  
 # First run tutorial.glade through gtk-builder-convert with this command:  
 # gtk-builder-convert tutorial.glade tutorial.xml  
 # Then save this file as tutorial.py and make it executable using this command:  
 # chmod a+x tutorial.py  
 # And execute it:  
 # ./tutorial.py  
 import pygtk  
 pygtk.require("2.0")  
 import gtk  
 class TutorialApp(object):      
      def __init__(self):  
        builder = gtk.Builder()  
        builder.add_from_file("tutorial.xml")  
        builder.connect_signals({ "on_window_destroy" : gtk.main_quit })  
        self.window = builder.get_object("window")  
        self.window.show()  
 if __name__ == "__main__":  
      app = TutorialApp()  
      gtk.main()  

다시, 나는 이 도움글에서 GUI를 구현하는데 사용하는 코드를 자세히 설명하지는 안고, Glade3에만 집중하겠다.

GtkWindow에 Widget 추가하기

reference documentation for a GtkWindow를 다시 살펴보면, GtkWindow는 GtkContainer의 파생물이라는 것을 알 수 있다. GtkContainer로 부터 유도된 Widget들은 container widget들이다. 즉, 다른 widget들을 포함할 수 있다는 것을 의미한다. 이것은 GTK+ 프로그래밍에 또 다른 기본적인 개념 중 하나이다. 여러분이 Windows기반의 프로그래밍 경험이 있다면, widget을 window에 놓고 원하는 위치에 어디에나 옮기는 작업을 하기 원할 것이다. 그러나 이러한 작업은 GTK+가 작동하는 방법이 아니다.

그리고 몇 가지 좋은 이유 때문에 GTK+ widget들은 다양한 container에 "packed"(합성)된다. Container들은 다른 container에 합성될 수 있고 계속적으로 다른 container에 합성 될 수 있다. widget을 위한 공간이 얼마나 할당되어 있느냐에 따라 container에 효과적으로 합성되는 다양한 속성들을 가지고 있다. 이러한 합성 속성들과 문턱 container를 통해서, 우리는 복잡한 GUI 디자인을 widget의 위치조정과 크기조절하는 코드의 작성 없이 할 수 있다.

이건 아마도 새내기 GTK+ 개발자에게 아주 어려운 개념중 하나일 것이다. 그러니깐 그냥 진행하면서 살펴보도록 하자!

GtkWindow 는 하나의 자식 widget만 합성할 수 있는 GtkBin container의 파생물이다. 그러나 이 text editer는 3개의 색션을 가지고 있다: 메뉴 바, 문서 편집 영역, 그리고 상태바. 그러므로, 우리는 기본적인 GTK+ widget, GtkVBox를 사용한다. GtkVBox (수직 박스)는 어떠한 개수의 자식 widget들도 수직방향으로 적층하여 합성할 수 있는 container widget이다. (GtkHBox는 수평방향으로 가능하다.)

'Container'색션 아래 Glade 팔레트에 있는 GtkVBox 아이콘 을 클릭하자. Glade 윈도우의 맨 위쪽에 있는 'Select' 툴바 버튼은 더이상 비 활성화 상태로 되어있지 않을 것이다. 그리고 마우스 커서는 Glade Editor 영역에 머물때 (+)기호를 가지면서 GtkVBox 아이콘으로 나타날 것이다. 이건 GtkVBox를 어디엔가 놓아둘 준비가 되어 있다는 것을 의미한다. GtkWindow의 빈 영역인 Editor 영역의 회색 영역을 클릭하자.

'Number of items'을 묻는 팝업 메뉴가 뜰것이다. 여기서 우리는 3개의 열을 원하기 때문에 3으로 놓고 OK를 클릭하자.


Editor 영역에 있는 GtkWindow가 3개의 열로 나누어진 것을 확인하라. 이건 GtkVBox에 추가할 수 있는 3개의 빈 Widget이라고 보면 된다. 그리고 Glade의 맨위쪽의 'Select' 툴바를 다시한번 눌려지지 않은 상태로 놓아 두자. Editor영역 내에서 widget을 선택할 수 있도록 하기 위해서.


다음으로, 'Container'아래의 Glade Palette에 있는 GtkMenuBar 아이콘 을 클릭하자. GtkVBox의 맨 위 열에 이것을 놓아 두자.


그럼 'Containers'아래 Glade Palette에 있는 GtkScrolledWindow 아이콘 을 클릭하고, GtkVBox의 중간 영역에 놓아 두자. 이 작업을 한다고 무언가 달라지지는 안지만, 중간 영역이 선택된 상태처럼 보여 진다. 이건 GtkScrolled Window는 아니다. GtkScrolledWindow는 초기상황에 보여지는 항목이 아니기 때문에 아직 살펴 볼 수 없다. 이건 자식 widget이 많이 커져 버렸을 때 scroll bar를 제공해 주는 하나의 container다. 우리는 이것이 text editing widget을 위해서 필요하다.


'Control and Display' 아래 Glade Palette에 있는 GtkTextView 아이콘 을 클릭하고, 중간 열에 있는 GtkScrolledWindow의 윗 부분의 오른쪽에 놓아 두자. 그럼 GtkVBox에 추가된 GtkScrolledWindow에 GtkTextView를 막 추가한게 된다.


마지막으로, 'Control and Display'아래 Glade Palette에 있는 GtkStatusbar 아이콘 을 클릭하고, 맨 아래 열에 놓아 두자.


그리고 나면 여러분은 GTK+ text editor의 기본적인 모양새를 구성하게 된다. Glade Inspector를 보면 우리의 디자인에 대한 부모 자식간의 관계를 볼 수 있다.


Inspector 는 다루기 쉽게 되어 있다. Widget이 보이지 않는 상태면 Editor영역에서 클릭을 할 수 없기 때문에, 예를 들면, 추가한 GtkScrolledWindow는 클릭할 수 없다. 그져 그 자식에 해당하는 GtkTextView만 볼 수 있다. 그러므로 "scrolledwindow1"의 속성을 변경하고자 한다면, Inspector에 가서 살펴보아야 한다.

나는 처음에 "packing"이라는 개념이 새내기 GTK+ 개발자들을 좌절시킨다고 이야기 했었다. 그러므로, 나는 디자인의 모양새을 구성하는 얼마나 많은 합성 효과있는지 그져 한번 보여주기만 하겠다.

모양새를 이루는 다양한 합성 효과들

우리가 디자인한 인터페이스를 계속 보게되면, 여러분은 아마도 Glade가 얼마나 "smart"한지를 모르고 지나칠지도 모른다. 우리가 status bar 를 높아 지지 않기를 원한다는 것을 어떻게 알아서 처리하고, window의 크기를 변경할때 어떻게 문자 편집영역에 새로운 수직공간을 만들면서 생성되는지? Glade는 잘 예상한다. 그건 우리가 자주 사용하는 (매번은 아니지만) 초기 합성 옵션에 적용 되기 때문이다.

합성에 관한 것을 배우는 가장 좋은 방법은 실제로 어떤효과가 나타나는지 볼 수 있도록 Glade의 packing properties를 가지고 작업을 해보는 것이다. 먼저, 적용가능한 속성을 간단히 살펴보자. GTK+를 한번 생각해 보면, 여러분은 packing과 공간 생성에 대해서 좀더 읽어 보길 원하게 될것이다.
  • homogeneous: container widget의 속성으로 활성화 되었을때 GTK+가 모든 자식에게 같은 공간을 할당하도록 한다.
  • expand: 부모가 커졌을때 추가적인 공간을 받는자식의 속성
  • fill: 추가적인 공간이 자식 주위에 padding으로 사용될지 자식에게 주어질지를 결정하는 자식의 속성

우리 디자인의 초기 packing 설정을 보자. GtkScrolledWindow는 부모가 커졌을때 추가적인 공간을 받을 수 있도록 "expand"=TRUE로 되어 있고 추가적인 공간을 제공받았을때 그것을 사용한다는 의미인 "fill"=TRUE로 되어 있다. 이것은 우리가 원하는 작동 방식이다.

WidgetPropertyValue
GtkVBox "vbox1"homogeneousFALSE
GtkMenuBar "menubar1"expandFALSE
fillTRUE
GtkScrolledWindow "scrolledwindow1"expandTRUE
fillTRUE
GtkStatusbar "statusbar1"expandFALSE
fillTRUE

그 럼 뭐가 homogeneous 한지를 이야기 하는지 부터 살펴보자. Glade Inspector에서 GtkVBox를 선택하자 그리고 그것의 'General' properties 탭아래 있는 "Homogeneous" 속성을 "Yes"로 변경하자. 그럼 부모인 "vbox1"은 자식들에게 동일한 공간을 할당한다. 3개의 자식모드 "fill=TRUE 로 되어 있기 때문에, 그들은 추가적인 공간들을 다 채울 것이다.


"Homogeneous" 속성을 "No"로 되돌리자.

Glade Inspector에서 GtkScrolledWindow "scrolledwindow1"를 클릭하고, 'Packing' properties 탭의 "Expand" 속성을 "No"로 설정하자. 그럼 어떤 자식도 GtkVBox가 커질때 추가적은 공간을 받지 않을 것이다. 나는 아래에 묘사된되로 3개의 자식들을 보기 쉽게 색칠해 놓았다. 각각의 자식 widget들은 초기에 설정된 크기를 가지고 있다. GtkVBox에 할당된 추가적인 공간은 그 자식들이 원하지 않기 때문에 그져 미사용 형태로 남아았다. (그러나 여전히 GtkVBoxdp 소속된 형태로 남아 있다.)


그럼 GtkScrolledWindow의 "Expand"속성을 "Yes"로 되돌리고 "Fill"속성을 "No"로 두자. 그럼 추가적인 공간은 GtkScrolledWindow의 "expand"가 TRUE이기 때문에 제공되지만, GtkScrolledWindow은 "fill"=FALSE이기 때문에 그 공간을 사용하지 않는다.


처음의 packing속성으로 되돌리기 위해서 "Fill"을 "Yes"로 설정하자.

나 는 이것이 처음엔 이상하게 느겨질 것이라는 것은 안다. 하지만, 여러분이 Glade에서 작업을 계속해 나아감에 따라서 어떤 packing 속성들이 어떻게 동작하는지를 이해하게 될 것이다. 여러분이 배우는 과정의 전환점을 한번 정복하게 되면 GUI의 각 항목의 크기와 위치에 관한 작업이 어떻게 이루어 지는지 놀라게 될 것이다.

메뉴(혹은 툴바) 편집하기

Glade3 는 새로운 Menu와 Toolbar editor를 가지게 됬다. 우리는 이 도움글에서 GtkToolbar를 사용하지는 않지만, 이 과정은 GtkMenubar에서 하는 작업과 매우 유사하다. 우리는 사용하지 항목들을 제거하고, 우리가 사용하게될 menu 항목에서 발생하는 signal 다룸자를 설정하기 위해서 Glade3 Menu Editor 를 사용할 것이다.

표준 Glade properties 패널에서 GtkMenuItems의 signal과 속성들을 생성하고 Glade Inspector 에서 항목을 제거할 수있지만, Glade3 menu editor는 여러분의 application의 메뉴를 편집하는 쉬운 방법을 제공한다.

Glade Inspector나 Glade Editor에서 GtkMenuBar를 선택하자. 그럼 오른쪽 버튼을 클릭해서 팝업메뉴를 만들고 'Edit'항목을 선택하자. 그럼 menu editor가 구동될 것이다.


menu editor는 Glade's main Properties 패널과 같은 속성들 Glade's main Properties의 'Signals' 탭에서 제공하는 signal들을 아래에 가지고 있다. editor에서 크게 다른점은 왼쪽의 tree view다. 이것은 menu의 항목을 쉽게 추가 하고 제가하게 해준다. 맨 앞으로 가서 "_View"로 된 것을 제거하자. 이것은 이번 도움글에서 사용하지 않는 Glade에서 생성된 메뉴 항목이다.

남아 있는 메뉴 항목에 대해서, 우리는 약간의 작업이 필요하다. 소스코드에서 참조하기에 명확하고 읽기 쉬운 상태로 만들기 위해서 이름을 바꾸자. 그럼, GTK+ 2.12.9 나 그 이하의 버전(Bug #523932) 을 사용하는 독자에 영향을 주는 버그 주변의 작업에 약간의 변경을 가하자. 이 과정은 모든 메뉴의 항목에 동일하게 적용되기 때문에 'New'라는 menu 항목에 대해서만 작업을 해본다. 이 작엄은 모두 menu editor에서 이루어 지지만, Inspector나 Properties에서도 가능하다는 것을 기억하자.

  1. new menu 항목 'gtk-new'를 클릭하자.
  2. 'Menu Item'아래 'Name' 속성을 "new_menu_item"로 변경하자.
  3. 'Properties'아래 'Label'속성을 "_New"로 변경하자 ('_'의 다음 글자는 단축키로 사용된다.)
  4. 'Properties'아래 'Stock Item'속성을 "None"으로 변경하자.
  5. 'gtk-open'과 같은 다름 menu 항목을 클릭하고 속성을 환기시키기 위해서 'gtk-new'로 되돌아가 클릭하자(Bug #533503)
  6. 'Internal Image Properties'아래 'Stock Image'를 'New' image로 변경하자.
  7. "on_new_menu_item_activate"로 불리는 "activate" signal을 위한 도움자를 설정하자. (이건 전에 했었던거 처럼하면 된다.  가능한 signal 이름을 drop down 항목을 얻기위해서 tree view를 클릭하자.)

그럼 이 과정을 모든 menu 항목에 대해서 반복하자: 'gtk-open', 'gtk-save', etc. 아래는 'New' 메뉴 항에 적용하기 전과 후의 갈무리이다.


Glade Menu Editor before changes



Glade Menu Editor after changing 'New' menu item


Main Window에 해야할 마지막 손길

여러분이 코딩을 할때, "textview1"과 "textview2" 같은 reference를 이해하는 것은 전혀 쉬운일이 아니다. 그래서 다음 widget들의 이름과 속성을 변경하자(name은 Properties 패널의 'General' 탭에 있다. ):
  1. "textview1"은 "text_view"으로 바꾸자.
  2. "statusbar1"은 "statusbar"으로 바꾸자.

scroll bar가 보여질때 좀더 멋있게 보여지게 만들기 위해서 GtkScrolledWindow에 border와 shadow를 추가하자.
  1. "scrolledwindow1"의 'General' properties 탭에 있는 "Shadow Type"을 "Etched In' 으로 변경하자.
  2. "scrolledwindow1"의 'Common' properties 탭에 있는 "Border Width"을 1로 변경하자.
  3. "text_view"의 'General' properties 에 있는 "Left Margin"를 2로 변경하자.
  4. "text_view"의 'General' properties 에 있는 "Right Margin"을 2로 변경하자.


    The finished glade file can be downloaded here: tutorial.glade

    Getting Additional Help Using Glade

    If you have additional questions about using Glade, you can always ask on the glade-users mailing list or post your question in the GTK+ Forums.

    What Next?

    In GTK+ and Glade3 GUI Programming Tutorial - Part 2 I will talk a little bit about choosing a programming language to implement the GUI we just created.
    If you don't want to read along and would rather just see the final implementations:

    댓글 4개:

    1. 번역감사합니다. glade 를 배우는데 큰 도움이 되었습니다. ^^

      답글삭제
    2. 저도 감사드립니다.

      답글삭제
    3. 감사합니다. 잘 읽었습니다.

      답글삭제