Blob Blame History Raw
<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" type="topic" id="image-viewer.js" xml:lang="ko">

  <info>
  <title type="text">그림 보기(JavaScript)</title>
    <link type="guide" xref="js#examples"/>

    <desc>간단한 "Hello world" 프로그램에 약간의 무언가가 더 들어갑니다 - GTK+의 그림 보기를 작성합니다. JavaScript 언어 소개 내용도 들어있습니다.</desc>

    <revision pkgversion="0.1" version="0.1" date="2011-03-19" status="review"/>
    <credit type="author">
      <name>Jonh Wendell</name>
      <email its:translate="no">jwendell@gnome.org</email>
    </credit>
    <credit type="author">
      <name>Johannes Schmid</name>
      <email its:translate="no">jhs@gnome.org</email>
    </credit>
    <credit type="editor">
      <name>Marta Maria Casetti</name>
      <email its:translate="no">mmcasettii@gmail.com</email>
      <years>2013</years>
    </credit>
  
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
      <mal:name>조성호</mal:name>
      <mal:email>shcho@gnome.org</mal:email>
      <mal:years>2017</mal:years>
    </mal:credit>
  </info>

<title>그림 보기</title>

<synopsis>
  <p>아 따라하기 안내서에서는 그림 파일을 불러와서 나타내는 매우 간단한 GTK 프로그램을 작성해보겠습니다. 다음 내용을 배웁니다:</p>
  <list>
    <item><p>JavaScript로 기본 GTK 사용자 인터페이스 작성하기</p></item>
    <item><p>시그널 핸들러에 시그널을 연결하여 이벤트 처리하기</p></item>
    <item><p>컨테이너로 GTK 사용자 인터페이스 배치하기</p></item>
    <item><p>그림 파일 불러오고 표시하기</p></item>
  </list>
  <p>이 지침을 따라갈 수 있으려면 다음이 필요합니다:</p>
  <list>
    <item><p><link xref="getting-ready">안주타 IDE</link> 설치 사본</p></item>
    <item><p><em>gjs</em> 인터프리터 설치 사본</p></item>
    <item><p>객체지향 프로그래밍 언어 기본 지식</p></item>
  </list>
</synopsis>

<media type="image" mime="image/png" src="media/image-viewer.png"/>

<section id="anjuta">
  <title>안주타에서 프로젝트 만들기</title>
  <p>코딩을 시작하기 전에 안주타에서 새 프로젝트를 설정해야합니다. 이 프로그램은 빌드에 필요한 모든 파일을 만들고 그 다음 코드를 실행합니다. 또한 이 모든 상태를 유지 관리하는데 쓸만합니다.</p>
  <steps>
    <item>
    <p>안주타를 시작하고 <guiseq><gui>파일</gui><gui>새로 만들기</gui><gui>프로젝트</gui></guiseq> 를 눌러 프로젝트 마법사를 여십시오.</p>
    </item>
    <item>
    <p><gui>JS</gui> 탭에서 <gui>일반 Javascript</gui>을 선택하고 <gui>다음</gui>을 누른 후 일부 페이지에 세부 내용을 채워나가십시오 프로젝트 이름과 디렉터리 이름을 <file>image-viewer</file>로 설정하십시오.</p>
   	</item>
    <item>
    <p><gui>적용</gui>을 누르면 프로젝트를 만들어줍니다. <gui>프로젝트</gui>나 <gui>파일</gui>탭에서 <file>src/main.js</file> 파일을 여십시오. 매우 기본적인 예제 코드가 들어있습니다.</p>
    </item>
  </steps>
</section>


<section id="js">
  <title>JavaScript 기본: Hello World</title>
  <p>그림 보기 프로그램 작성을 시작하기 전에 그놈에서 JavaScript를 활용하는 방법을 더 알아보기로 하겠습니다. 아, 물론 어떤 프로그래밍 언어를 처음 접하는 코드는 <file>main.js</file> 파일로도 찾을 수 있는 Hello world 프로그램입니다:</p>
  <code mime="application/javascript">print ("Hello world!");</code>
  <p>다른 대부분의 프로그래밍 언어에 익숙하다면 이 부분이 자연스러워 보일지도 모르겠습니다. <code>print</code> 함수는 화면에 출력할 <code>"Hello world!"</code> 인자 값으로 호출합니다. 참고로 각 코드의 줄은 세미콜론으로 끝납니다.</p>
</section>

<section id="classes">
  <title>JavaScript 클래스</title>
  <p>이 방법이 JavaScript에서 클래스를 정의하는 표준 방식입니다:</p>
  <code mime="application/javascript" style="numbered">
function MyClass () {
  this._init ();
}

MyClass.prototype = {

  _init: function () {
    this.propertyA = "This is an object's field";
    this.propertyB = 10;
  },

  aMethod: function (arg1, arg2) {
    print ("inside aMethod: " + arg1 + " " + arg2);
  },

  dumpProperties: function () {
    print (this.propertyA);
    print (this.propertyB);
  }

}</code>
  <p><code>MyClass</code> 클래스를 정의합니다. 클래스 정의 각 부분을 살펴보겠습니다:</p>
  <steps>
    <item>
    <p><code>function MyClass</code> 는 클래스 생성자입니다. 이름은 클래스 이름과 같아야합니다. <code>this</code> 객체를 활용하여 클래서의 어떤 구성원이든 접근할 수 있습니다. 여기서, 생성자는 클래스의 <code>_init</code> 메서드를 호출합니다.</p>
    </item>
    <item>
    <p><code>MyClass.prototype</code> 블록은 클래스의 <em>structure</em>를 정의합니다. 각 클래스는 메서드(함수)와 필드(변수)로 만듭니다. 예제에서는 메서드 3개와 필드 2개로 이루어졌습니다.</p>
    </item>
    <item>
    <p>여기서 정의한 첫 메서드는 <code>_init</code>이며, 인자 값을 주지 않는 함수로 지정합니다:</p>
    <code>_init: function ()</code>
    <p>중괄호 안에 함수를 작성하겠습니다. <code>propertyA</code>와 <code>propertyB</code> 필드 두개를 여기에서 정했습니다. 처음은 문자열로 설정하고 두번째는 정수(10진수) 값으로 설정합니다. 이 함수는 어떤 값도 반환하지 않습니다.</p>
    </item>
    <item>
    <p>다음 메서드는 <code>aMethod</code>이며, 이 함수를 호출할 때 화면에 출력할 인자 두 개가 있습니다. 마지막은 <code>propertyA</code>, <code>propertyB</code> 필드를 출력하는 <code>dumpProperties</code>메서드입니다.</p>
    </item>
    <item>
    <p>클래스 정의(프로토타입) 정돈 법을 정리해두십시오. 각 함수 정의는 쉼표로 구분합니다.</p>
    </item>
  </steps>

  <p>이제 MyClass 클래스를 정의했으니 가지고 놀 수 있습니다:</p>
  <code mime="application/javascript" style="numbered">
var o = new MyClass ();
o.aMethod ("Hello", "world");
o.propertyA = "Just changed its value!";
o.dumpProperties ();</code>
  <p>이 코드는 클래스의 새 인스턴스 <code>o</code>를 만들고, <code>aMethod</code>를 실행하며 <code>propertyA</code> 값을 다른 문자열 값으로 바꾼 후, (필드 내용을 출력하는) <code>dumpProperties</code> 메서드를 호출합니다.</p>
  <p><file>main.js</file> 코드를 저장하고 메뉴에서 <guiseq><gui>실행</gui><gui>실행</gui></guiseq>을 누르거나 도구 모음의 단추를 눌러 실행하십시오.</p>
</section>

<section id="gtk">
  <title>첫 gtk 프로그램</title>
  <p>JavaScript로 작성한 Gtk 프로그램의 가장 기본적인 부분이 어떻게 생겼는지 보도록 하겠습니다:</p>
  <code mime="application/javascript" style="numbered">
const Gtk = imports.gi.Gtk;

Gtk.init (null, null);

var w = new Gtk.Window ({title: "Image Viewer Demo"});
w.show ();

Gtk.main ();</code>
  <p>어떤 동작이 일어나는지 살펴보죠:</p>
  <list>
    <item>
    <p>첫 줄은 (Gtk 라이브러리가 있는) Gtk 이름 영역을 임포팅합니다. 라이브러리에는 많은 그놈 라이브러리의 언어 바인딩이 들어있는 GObject 인트로스펙션(gi)이 있습니다.</p>
    </item>
    <item>
    <p><code>Gtk.init</code>은 Gtk 라이브러리를 초기화합니다. 모든 Gtk 프로그램의 필수 구문입니다.</p>
    </item>
    <item>
    <p>다음 줄에서는 새 <code>Gtk.Window</code> 객체로 메인 창을 만듭니다. <code>{property: value, property: value, ...}</code> 문법으로 창 생성자에 몇가지 속성 값을 전달할 수 있습니다. 지금 같은 경우는 창 제목을 설정합니다.</p></item>
    <item><p>다음 줄에서는 분명하게 창을 보여줍니다. Gtk에서는 모든 창을 기본으로 숨겨둡니다.</p></item>
    <item><p>마지막으로 <code>Gtk.main</code>에서 메인 루프를 실행합니다. 다시 말해, 프로그램을 실행합니다. 메인 루프에서는 사용자 인터페이스의 이벤트(시그널)를 기다리며, 어디선가 내보낸 시그널을 찾으면 쓸만한 시그널 핸들러를 호출합니다. 시그널에 대해 간단하게 앞으로 더 알아볼 예정입니다.</p></item>
  </list>

  <p><file>main.js</file> 파일에 코드를 저장하고 실행해보십시오. 창을 닫아도 프로그램이 안 끝나는 모습이 나타납니다. 아직 창의 <code>destroy</code>(닫기) 시그널을 시그널 핸들러에서 처리하도록 설정하지 않았기 때문입니다. 곧 이 부분을 진행하겠지만, 지금은 터미널 창에서 <keyseq><key>Ctrl</key><key>C</key></keyseq> 키를 눌러 프로그램을 끝낼 수 있습니다.</p>

</section>

<section id="classes2">
  <title>클래스 추가</title>
  <p>적당한 Gtk 프로그래밍 방식은 클래스 사용 방식입니다. 간단한 코드를 클래스 코드로 다시 작성해보도록 하겠습니다:</p>
  <code mime="application/javascript" style="numbered">
const Gtk = imports.gi.Gtk;

function ImageViewer () {
  this._init ();
}

ImageViewer.prototype = {
  _init: function () {
    this.window = new Gtk.Window ({title: "Image Viewer Demo"});
    this.window.show ();
  }
}

Gtk.init (null, null);
var iv = new ImageViewer ();
Gtk.main ();</code>
  <!-- FIXME: Throws an error, "JS ERROR: !!!   Unhandled type int32 releasing GArgument" on Ubuntu 10.10 -->
  <p>프로그램이 같다는 사실을 알아채실겁니다. 창을 만드는 코드를 <code>ImageViewer</code>클래스로 옮겼을 뿐입니다. 이 클래스 생성자에서는 창을 만들고 보여주는 <code>_init</code> 메서드를 호출합니다. 그 다음 메인 루프(<code>Gtk.main</code>)를 실행하기 전 클래스의 인스턴스를 만듭니다.</p>
  <p>이 코드는 모듈식이며 여러 파일로 쉽게 나눌 수 있습니다. 이렇게 하면 코드가 간명해지고 알아보기 쉬워집니다.</p>
</section>

<section id="signals">
  <title>시그널</title>
  <p>시그널은 Gtk 프로그래밍의 핵심 개념입니다. 객체에 언제 어떤 일이 일어나든지 시그널을 내보냅니다. 예를 들어 단추를 누르면 <code>clicked</code> 시그널을 내줍니다. 동작이 일어났을때 프로그램에서 무언가를 하게 하려면 시그널에 함수(시그널 핸들러)를 연결해야합니다. 예제는 다음과 같습니다:</p>
  <code mime="application/javascript" style="numbered">
function button_clicked () {
  print ("you clicked me!");
}
var b = new Gtk.Button ({label:"Click me"});
b.connect ("clicked", button_clicked);</code>
  <p>마지막 두 줄은 <code>Gtk.Button</code>의 인스턴스 <code>b</code>를 만들고 <code>clicked</code> 시그널을 위에서 정의한 <code>button_clicked</code> 함수에 연결합니다. 항상 단추를 누를 때마다 <code>button_clicked</code> 함수를 실행합니다. 이 함수는 여기에 적어둔 메시지를 출력하는 동작만 합니다.</p>
  <p>시그널을 함수에 연결하는 문법은 다음과 같습니다:</p>
  <code mime="application/javascript">
object.connect (&lt;signal_name&gt;, &lt;function_to_be_called&gt;);</code>
  <p><link href="https://developer.gnome.org/gtk3/stable/gtkobjects.html">GTK 클래스 참고서</link>에서 임의의 객체에 대한 시그널 정의를 찾아볼 수 있습니다.</p>

  <note>
    <p>인라인 함수 정의 활용으로 코드를 단순하게 작성할 수 있습니다:</p>
    <code mime="application/javascript">
b.connect ("clicked", function () { print ("you clicked me!"); });</code>
  </note>

</section>

<section id="close">
  <title>창 닫기</title>
  <p>Gtk 창을 닫을 때 실제로는 창이 닫히지 않고 숨겨져 있습니다. 이렇게 하여 창을 유지할 수 있습니다(예를 들자면 사용자에게 정말 창을 닫을지 물어볼 때 이런 방식이 쓸만합니다).</p>
  <p>지금과 같은 경우는 창을 실제로 닫으려고 합니다. 가장 간단하게 처리하는 방법은 프로그램을 닫는 함수에 GtkWindow 객체의 <code>hide</code> 시그널을 연결하는 방법입니다. <file>image-viewer.js</file> 파일로 돌아가서 다음 코드를 <code>_init</code> 메서드의 <code>this.window.show</code> 코드 위에 추가하십시오:</p>
  <code mime="application/javascript" style="numbered">this.window.connect ("hide", Gtk.main_quit);</code>
  <p>이 코드는<code>hide</code> 시그널을 Gtk 메인 루프 실행을 끝내는 Gtk의 <code>main_quit</code> 함수에 연결합니다. 메인 루프를 끝내고 나면 <code>Gtk.main</code> 함수에서 반환 값을 내보냅니다. 이 프로그램에서는 <code>Gtk.main ();</code> 코드 줄 다음에 작성한 어떤 코드든 계속 실행하려 하겠지만 이후에 어떤 코드도 없기 때문에 프로그램을 그냥 끝냅니다.</p>
</section>

<section id="containers2">
  <title>컨테이너: 사용자 인터페이스를 두는 공간</title>
  <p>(단추 레이블 같은 컨트롤) 위젯은 <em>컨테이너</em>를 사용하여 창에서 배치를 정돈할 수 있습니다. 박스, 그리드 등 여러가지 형태의 컨테이너를 섞어 사용하여 배치를 이룰 수 있습니다.</p>
  <p><code>Gtk.Window</code>는 그 자체로 컨테이너의 한 종류지만 이 컨테이너에는 위젯을 한번에 하나씩만 넣을 수 있습니다. 여기에 우리는 그림과 단추, 두가지 위젯을 넣으려고 하기 때문에, 창 하나에 다른 위젯을 붙여둘 "공간이 더 많은" 컨테이너를 넣어야합니다. 쓸 수 있는 <link href="http://library.gnome.org/devel/gtk/stable/GtkContainer.html">컨테이너 형식</link>은 여러가지가 있지만, 여기서는 <code>Gtk.Box</code>를 사용합니다. <code>Gtk.Box</code> 는 가로 세로 방향으로 여러 위젯을 붙일 수 있습니다. 다른 여러가지 박스를 붙여서 보다 더 복잡한 배치를 만들 수 있습니다.</p>
  <note>
  <p><app>안주타</app>에 통합한 <app>글레이드</app> 사용자 인터페이스 디자인 프로그램이 있습니다. 이 프로그램은 사용자 인터페이스를 쉽게 만들 수 있게 해줍니다. 그러나 이 간단한 예제로 모든 코드를 직접 작성해보겠습니다.</p>
  </note>
  <p>박스와 위젯을 창에 추가해보겠습니다. 다음 코드를 <code>_init</code> 메서드의 <code>this.window.show</code>줄 바로 위에 넣으십시오:</p>
  <code mime="application/javascript" style="numbered">
var main_box = new Gtk.Box ({orientation: Gtk.Orientation.VERTICAL, spacing: 0});
this.window.add (main_box);</code>
  <p>첫 줄은 <code>Gtk.Box</code>의 인스턴스 <code>main_box</code>를 만들고 인스턴스의 속성 두개를 설정합니다. <code>orientation</code>은 수직 방향으로 설정(따라서 위젯을 수직 방향으로 배치합니다)하고, 위젯 사이의 공간 <code>spacing</code> 값은 0 픽셀로 설정합니다. 다음 줄은 창에 새로 만든 <code>Gtk.Box</code>를 추가합니다.</p>
  <p>지금까지 창에는 빈 <code>Gtk.Box</code>만 넣었기에 지금 프로그램을 실행하면 어떤 변화도 없음을 볼 수 있습니다(<code>Gtk.Box</code>는 투명 컨테이너라서 그 무엇도 볼 수 없습니다).</p>
</section>

<section id="packing2">
  <title>패킹: 컨테이너에 위젯 추가</title>
  <p>일부 위젯을 <code>Gtk.Box</code>에 추가하려면 다음 코드를 직접 <code>this.window.add (main_box)</code> 코드 줄 아래에 넣으십시오:</p>
  <code mime="application/javascript" style="numbered">
this.image = new Gtk.Image ();
main_box.pack_start (this.image, true, true, 0);</code>
  <p>첫 줄에서는 그림 파일을 나타낼 때 쓸 새 <code>Gtk.Image</code> 인스턴스 <code>image</code>를 만듭니다. 그 다음 그림 위젯을 <code>Gtk.Box</code>의 <link href="http://library.gnome.org/devel/gtk/stable/GtkBox.html#gtk-box-pack-start"><code>pack_start</code></link> 메서드로 <code>main_box</code>에 추가(<em>패킹</em>)합니다.</p>
  <p><code>pack_start</code> 메서드에는 <code>Gtk.Box</code>에 추가할 위젯(<code>child</code>) 인자, 새 위젯을 추가했을 때 <code>Gtk.Box</code>를 더 크게 할지 여부(<code>expand</code>) 인자, <code>Gtk.Box</code>가 커졌을 때 모든 여분 공간을 차지할 지 여부(<code>fill</code>) 인자, <code>Gtk.Box</code>에서 위젯 간 설정할 간격(<code>padding</code>) 인자가 있습니다.</p>
  <p>Gtk 컨테이너(와 위젯)은 여분 공간을 동적으로 채우도록 설정하면 그렇게 보여줍니다. 창에서 정확한 x,y 좌표 값을 주어 위젯 위치를 설정할 수 없습니다. 다만 서로 상대적 위치에 둘 수 있습니다. 이렇게 하면 창 크기 조절을 더 쉽게할 수 있고, 위젯든 대부분의 경우 타당한 크기를 가집니다.</p>
  <p>또한 위젯은 서로 계층적 관계를 가짐을 참고하십시오. <code>Gtk.Box</code>에 패킹하면, <code>Gtk.Image</code>는 <code>Gtk.Box</code>의 <em>하위 요소</em>로 간주합니다. 이렇게 하여 모든 하위 위젯을 그룹 단위로 다룰 수 있습니다. 예를 들면, <code>Gtk.Box</code>와 이 컨테이너에 들어있는 모든 하위 컨테이나와 위젯을 동시에 숨길 수 있습니다.</p>
  <p>이제 다음 두 줄을 방금 추가한 두 줄 아래에 추가하십시오:</p>
  <code mime="application/javascript" style="numbered">
var open_button = new Gtk.Button ({label: "Open a picture..."});
main_box.pack_start (open_button, false, false, 0);</code>
  <p>이 줄은 처음 두 줄과 비슷하지만 <code>Gtk.Button</code>을 만들어 <code>main_box</code>에 추가합니다. 여기서 (두번째) <code>expand</code> 인자 값을 <code>Gtk.Image</code>에 대해서는 <code>true</code> 로 설정했음에 반해 <code>false</code>로 설정했음에 유의하십시오. 이 함수로 그림을 활용 가능한 공간을 차지하게 하며 단추는 필요한 공간만 차지하게 합니다. 창을 죄대로 확장하면 단추 크기는 그대로지만, 그림은 창 나머지 공간을 차지하면서 커집니다.</p>
  <p>마지막으로 <code>this.window.show ();</code> 함수를 다음으로 바꿔야합니다:</p>
  <code>this.window.show_all ();</code>
  <p>이 코드는 Gtk 창의 하위 구성 요소와 해당 요소의 모든 하위 구성 요소를 보여줍니다(기본적으로 Gtk 위젯은 숨겨둔 상태임을 기억하십시오).</p>
</section>

<section id="loading2">
  <title>그림을 불러옵니다: 단추의 <code>clicked</code> 시그널에 연결</title>
  <p>사용자가 <gui>열기</gui> 단추를 누르면, 대화 상자가 나타나 그림을 선택할 수 있습니다. 그림을 선택하고 나면 그림을 불러오고 그림 위젯에 표시합니다.</p>
  <p>첫 단계에서는 단추의 <code>clicked</code> 시그널을, 우리가 호출할 시그널 핸들러 함수 <code>_openClicked</code>에 연결합니다. 이 코드를 단추를 만드는 <code>var open_button = new Gtk.Button</code> 줄 바로 다음에 넣으십시오:</p>
  <code mime="application/javascript">
open_button.connect ("clicked", Lang.bind (this, this._openClicked));</code>
  <p><em>Lang</em> JavaScript 보조 라이브러리를 사용하고 있습니다. 창의 <code>hide</code> 시그널에 대한 (클래스 없는) 생짜 함수를 쓰기보다는, 시그널에 <em>클래스 메서드</em> 를 연결할 수 있습니다. 지금은 걱정하실 필요가 없습니다. 그냥 기술적으로 자세한 이야기일 뿐이죠. 동작하게 하려면 파일의 상단에 다음 줄을 넣어야합니다:</p>
  <code mime="application/javascript">const Lang = imports.lang;</code>
</section>

<section id="loading3">
  <title>그림 불러오기: 시그널 콜백 작성</title>
  <p>이제 <code>_openClicked()</code> 메서드를 만들었습니다. 다음 코드를 <code>_init</code> 메서드 다음의 <code>ImageViewer.prototype</code> 코드 블럭에 넣으십시오(그리고 콤마 표시를 빼먹지 마십시오):</p>
    <code mime="application/javascript" style="numbered">
  _openClicked: function () {
    var chooser = new Gtk.FileChooserDialog ({title: "Select an image",
                                              action: Gtk.FileChooserAction.OPEN,
                                              transient_for: this.window,
                                              modal: true});
    chooser.add_button (Gtk.STOCK_CANCEL, 0);
    chooser.add_button (Gtk.STOCK_OPEN, 1);
    chooser.set_default_response (1);

    var filter = new Gtk.FileFilter ();
    filter.add_pixbuf_formats ();
    chooser.filter = filter;

    if (chooser.run () == 1)
      this.image.file = chooser.get_filename ();

    chooser.destroy ();
  }</code>
  <p>지금까지 우리가 다루어왔던 어떤 코드보다 조금 복잡하니 하나씩 뜯어보도록 하겠습니다:</p>
  <list>
    <item>
      <p><code>var chooser</code>로 시작하는 줄에서는 사용자가 파일을 선택할 수 있는 <gui>열기</gui> 대화 상자를 만듭니다. 대화 상자 제목, 대화 상자 동작(형식) ("열기" 대화 상자지만, 파일을 저장하려고 할 때는 <code>SAVE</code>를 쓸 수 있습니다), 대화 상자의 상위 창을 설정하는 <code>transient_for</code>,  <code>true</code>로 설정하면 대화상자를 닫기 전까지 그 어떤 것도 누를 수 없게 하는 <code>modal</code> 속성을 지정합니다.</p>
    </item>
    <item>
    <p>다음 두 줄은 대화상자에 <gui>취소</gui> 단추와 <gui>열기</gui> 단추를 만듭니다. <code>add_button</code> 메서드의 두번째  인자는 단추를 눌렀을 때 반환하는 (정수) 값입니다. <gui>취소</gui>는 0, <gui>열기</gui>는 1입니다.</p>
    <p>참고로 "취소", "열기"를 직접 입력하는 대신, Gtk에서 <em>stock</em> 단추 이름을 활용합니다  스톡 이름은 사용자가 쓰는 언어로 미리 번역해둔 단추 레이블을 활용한다는 점입니다.</p>
    </item>
    <item>
    <p><code>set_default_response</code>에서는 파일을 두번 누르거나 <key>Enter</key> 키를 눌렀을 때 활성화 할 단추를 결정합니다. 지금의 경우는 <gui>열기</gui> 단추(단추 값은 1)를 기본으로 사용합니다.</p>
    </item>
    <item>
    <p>다음 두 줄은 <gui>열기</gui> 대화 상자에서 <code>Gtk.Image</code>로만 열 수 있는 파일을 표시하도록 제한합니다. 필터 객체를 우선 만듭니다. 그 다음 <code>Gdk.Pixbuf</code>에서 지원하는 파일 종류(PNG와 JPEG 같은 대부분의 그림 형식)를 필터에 추가합니다. 마지막으로 이 필터를 <gui>열기</gui> 대화 상자의 필터로 설정합니다.</p>
    </item>
    <item>
    <p><code>dialog.run</code>은 <gui>열기</gui> 대화 상자를 표시합니다. 대화 상자는 사용자의 그림 선택을 기다립니다. 사용자가 그림을 선택하면 <code>dialog.run</code> 에서 <output>1</output> 값을 반환합니다(<gui>취소</gui>를 누르면 <output>0</output> 값을 반환합니다). <code>if</code> 구문에서는 어떤 값을 반환했는지 확인합니다.</p>
    </item>
    <item><p>사용자가 <gui>열기</gui>를 눌렀다고 한 상황에서, 다음 줄에서 <code>Gtk.Image</code>의 <code>file</code> 속성 값을 사용자가 선택한 그림 파일 이름으로 설정합니다. <code>Gtk.Image</code>는 선택한 그림을 불러오고 화면에 표시합니다.</p>
    </item>
    <item>
    <p>이 메서드의 마지막 줄에서는 <gui>열기</gui> 대화상자는 더 이상 필요 없으니 해체합니다.</p>
    </item>
  </list>

  </section>

<section id="run">
  <title>프로그램 실행</title>
  <p>필요한 모든 코드를 제자리에 넣었으니 코드를 실행해보겠습니다. 제대로 동작할겝니다. 이렇게 하여 기능이 완전하게 동작하는 그림 보기 프로그램(JavaScript와 Gtk를 활용한 간단한 맛보기)을 그리 길지 않은 시간 동안에 만들었습니다!</p>
</section>

<section id="impl">
 <title>참조 구현체</title>
 <p>지침서를 따라하는 실행하는 과정에 문제가 있다면, <link href="image-viewer/image-viewer.js">참조 코드</link>와 여러분의 코드를 비교해보십시오.</p>
</section>

<section id="next">
  <title>다음 단계</title>
  <p>여기 간단한 시험 프로그램에 여러분이 추가로 넣을 수 있는 몇가지 아이디어가 있습니다:</p>
  <list>
   <item>
   <p>파일을 선택하기 보단 디렉터리를 선택하게 하고, 디렉터리의 모든 그림을 보여줄 수 있는 컨트롤을 제어 기능을 제공합니다.</p>
   </item>
   <item>
   <p>사용자가 그림을 불러오고 수정한 그림을 저장할 때 임의 필터와 효과를 그림에 적용하십시오.</p>
   <p><link href="http://www.gegl.org/api.html">GEGL</link>에서는 강력한 그림 편집 기능을 제공합니다.</p>
   </item>
   <item>
   <p>네트워크 공유, 스캐너, 다른 복잡한 공급원에서 그림을 불러올 수 있습니다.</p>
   <p>You can use <link href="http://library.gnome.org/devel/gio/unstable/">GIO</link> to handle network file transfers and the like, and <link href="http://library.gnome.org/devel/gnome-scan/unstable/">GNOME Scan</link> to handle scanning.</p>
   </item>
  </list>
</section>

</page>