Blame platform-demos/ca/image-viewer.vala.page

Packit 1470ea
Packit 1470ea
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" type="topic" id="image-viewer.vala" xml:lang="ca">
Packit 1470ea
Packit 1470ea
  <info>
Packit 1470ea
  <title type="text">Image viewer (Vala)</title>
Packit 1470ea
    <link type="guide" xref="vala#examples"/>
Packit 1470ea
Packit 1470ea
    <desc>A little bit more than a simple "Hello world" GTK+ application.</desc>
Packit 1470ea
Packit 1470ea
    <revision pkgversion="0.1" version="0.1" date="2011-03-18" status="review"/>
Packit 1470ea
    <credit type="author">
Packit 1470ea
      <name>Projecte de documentació del GNOME</name>
Packit 1470ea
      <email its:translate="no">gnome-doc-list@gnome.org</email>
Packit 1470ea
    </credit>
Packit 1470ea
    <credit type="author">
Packit 1470ea
      <name>Johannes Schmid</name>
Packit 1470ea
      <email its:translate="no">jhs@gnome.org</email>
Packit 1470ea
    </credit>
Packit 1470ea
    <credit type="author">
Packit 1470ea
      <name>Philip Chimento</name>
Packit 1470ea
      <email its:translate="no">philip.chimento@gmail.com</email>
Packit 1470ea
    </credit>
Packit 1470ea
    <credit type="editor">
Packit 1470ea
     <name>Tiffany Antopolski</name>
Packit 1470ea
     <email its:translate="no">tiffany.antopolski@gmail.com</email>
Packit 1470ea
    </credit>
Packit 1470ea
  <credit type="editor">
Packit 1470ea
    <name>Marta Maria Casetti</name>
Packit 1470ea
    <email its:translate="no">mmcasetti@gmail.com</email>
Packit 1470ea
    <years>2013</years>
Packit 1470ea
  </credit>
Packit 1470ea
  </info>
Packit 1470ea
Packit 1470ea
<title>Image viewer</title>
Packit 1470ea
<synopsis>
Packit 1470ea
  

In this tutorial you will create an application which opens and displays an image file. You will learn:

Packit 1470ea
  <list type="numbered">
Packit 1470ea
    <item>

How to set up a basic project using the <link xref="getting-ready">Anjuta IDE</link>.

</item>
Packit 1470ea
    <item>

How to write a <link href="http://developer.gnome.org/platform-overview/stable/gtk">Gtk application</link> in Vala

</item>
Packit 1470ea
    <item>

Some basic concepts of <link href="http://developer.gnome.org/gobject/stable/">GObject</link> programming

</item>
Packit 1470ea
Packit 1470ea
  </list>
Packit 1470ea
  

You'll need the following to be able to follow this tutorial:

Packit 1470ea
  <list>
Packit 1470ea
    <item>

Basic knowledge of the <link href="https://live.gnome.org/Vala/Tutorial">Vala</link> programming language.

</item>
Packit 1470ea
    <item>

An installed copy of <app>Anjuta</app>.

</item>
Packit 1470ea
    <item>

You may find the <link href="http://valadoc.org/gtk+-3.0/">gtk+-3.0</link> API Reference useful, although it is not necessary to follow the tutorial.

</item>
Packit 1470ea
  </list>
Packit 1470ea
</synopsis>
Packit 1470ea
Packit 1470ea
<media type="image" mime="image/png" src="media/image-viewer.png"/>
Packit 1470ea
Packit 1470ea
<section id="anjuta">
Packit 1470ea
  <title>Creació d'un projecte a l'Anjuta</title>
Packit 1470ea
  

Abans de començar a programar, heu de crear un projecte nou a l'Anjuta. L'Anjuta crearà tots els fitxers necessaris per, més endavant, construir i executar el codi. És molt útil per així mantenir-ho tot junt.

Packit 1470ea
  <steps>
Packit 1470ea
    <item>
Packit 1470ea
      

Start <app>Anjuta</app> and click <gui>Create a new project</gui> or <guiseq><gui>File</gui><gui>New</gui><gui>Project</gui></guiseq> to open the project wizard.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
      

From the <gui>Vala</gui> tab choose <gui>GTK+ (Simple)</gui>, click <gui>Continue</gui>, and fill out your details on the next page.

Packit 1470ea
      Use <file>image-viewer</file> as project name and directory.

Packit 1470ea
   	</item>
Packit 1470ea
    <item>
Packit 1470ea
      

Make sure that <gui>Use GtkBuilder for user interface</gui> is unchecked as we will create the UI manually in this tutorial.

Packit 1470ea
     <note>

Packit 1470ea
      You will learn how to use the interface builder in the <link xref="guitar-tuner.vala">Guitar-Tuner</link> tutorial.

</note>
Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
      

Click <gui>Continue</gui> then <gui>Apply</gui> and the project will be created for you.

Packit 1470ea
      Open <file>src/image_viewer.vala</file> from the <gui>Project</gui> or <gui>File</gui> tabs.
Packit 1470ea
      You will see this code:

Packit 1470ea
      
Packit 1470ea
using GLib;
Packit 1470ea
using Gtk;
Packit 1470ea
Packit 1470ea
public class Main : Object
Packit 1470ea
{
Packit 1470ea
Packit 1470ea
	public Main ()
Packit 1470ea
	{
Packit 1470ea
		Window window = new Window();
Packit 1470ea
		window.set_title ("Hello World");
Packit 1470ea
		window.show_all();
Packit 1470ea
		window.destroy.connect(on_destroy);
Packit 1470ea
	}
Packit 1470ea
Packit 1470ea
	public void on_destroy (Widget window)
Packit 1470ea
	{
Packit 1470ea
		Gtk.main_quit();
Packit 1470ea
	}
Packit 1470ea
Packit 1470ea
	static int main (string[] args)
Packit 1470ea
	{
Packit 1470ea
		Gtk.init (ref args);
Packit 1470ea
		var app = new Main ();
Packit 1470ea
Packit 1470ea
		Gtk.main ();
Packit 1470ea
Packit 1470ea
		return 0;
Packit 1470ea
	}
Packit 1470ea
}]]>
Packit 1470ea
    </item>
Packit 1470ea
  </steps>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="build">
Packit 1470ea
  <title>Build the code for the first time</title>
Packit 1470ea
  

The code loads an (empty) window from the user interface description file and shows it.

Packit 1470ea
  More details are given below; skip this list if you understand the basics:

Packit 1470ea
Packit 1470ea
  <list>
Packit 1470ea
    <item>
Packit 1470ea
      

The two using lines at the top import namespaces so we don't have to name them explicitly.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
      

The constructor of the Main class creates a new (empty) window and connects a <link href="https://live.gnome.org/Vala/SignalsAndCallbacks">signal</link> to exit the application when that window is closed.

Packit 1470ea
      

Connecting signals is how you define what happens when you push a button, or when some other event happens.

Packit 1470ea
      Here, the destroy function is called (and quits the app) when you close the window.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
      

The static main function is run by default when you start a Vala application.

Packit 1470ea
      It calls a few functions which create the Main class, set up and then run the application.
Packit 1470ea
      The <link href="http://valadoc.org/gtk+-3.0/Gtk.main.html">Gtk.main</link> function starts the GTK <link href="http://en.wikipedia.org/wiki/Event_loop">main loop</link>, which runs the user interface and starts listening for events (like clicks and key presses).

Packit 1470ea
    </item>
Packit 1470ea
  </list>
Packit 1470ea
Packit 1470ea
  

This code is ready to be used, so you can compile it by clicking <guiseq><gui>Build</gui><gui>Build Project</gui></guiseq> (or press <keyseq><key>Shift</key><key>F7</key></keyseq>).

Packit 1470ea
  

Change the <gui>Configuration</gui> to <gui>Default</gui> and then press <gui>Execute</gui> to configure the build directory.

Packit 1470ea
  You only need to do this once, for the first build.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="ui">
Packit 1470ea
  <title>Creating the user interface</title>
Packit 1470ea
  

Now we will bring life into the empty window.

Packit 1470ea
  GTK organizes the user interface with <link href="http://www.valadoc.org/gtk+-2.0/Gtk.Container.html">Gtk.Container</link>s that can contain other widgets and even other containers.
Packit 1470ea
  Here we will use the simplest available container, a <link href="http://unstable.valadoc.org/gtk+-2.0/Gtk.Box.html">Gtk.Box</link>.

Packit 1470ea
Packit 1470ea

Add the following lines to the top of the Main class:

Packit 1470ea
  
Packit 1470ea
private Window window;
Packit 1470ea
private Image image;
Packit 1470ea
]]>
Packit 1470ea
Packit 1470ea

Now replace the current constructor with the one below:

Packit 1470ea
Packit 1470ea
Packit 1470ea
public Main () {
Packit 1470ea
Packit 1470ea
	window = new Window ();
Packit 1470ea
	window.set_title ("Image Viewer in Vala");
Packit 1470ea
Packit 1470ea
	// Set up the UI
Packit 1470ea
	var box = new Box (Orientation.VERTICAL, 5);
Packit 1470ea
	var button = new Button.with_label ("Open image");
Packit 1470ea
	image = new Image ();
Packit 1470ea
Packit 1470ea
	box.pack_start (image, true, true, 0);
Packit 1470ea
	box.pack_start (button, false, false, 0);
Packit 1470ea
	window.add (box);
Packit 1470ea
Packit 1470ea
	// Show open dialog when opening a file
Packit 1470ea
	button.clicked.connect (on_open_image);
Packit 1470ea
Packit 1470ea
	window.show_all ();
Packit 1470ea
	window.destroy.connect (main_quit);
Packit 1470ea
}
Packit 1470ea
]]>
Packit 1470ea
  <steps>
Packit 1470ea
    <item>
Packit 1470ea
      

The first two lines are the parts of the GUI that we will need to access from more than one method.

Packit 1470ea
      We declare them up here so that they are accessible throughout the class instead of only in the method where they are created.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
      

The first lines of the constructor create the empty window.

Packit 1470ea
      The next lines create the widgets we want to use: a button for opening up an image, the image view widget itself and the box we will use as a container.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
      

The calls to <link href="http://unstable.valadoc.org/gtk+-2.0/Gtk.Box.pack_start.html">pack_start</link> add the two widgets to the box and define their behaviour.

Packit 1470ea
      The image will expand into any available space whereas the button will just be as big as needed.
Packit 1470ea
      You will notice that we don't set explicit sizes on the widgets.
Packit 1470ea
      In GTK this is usually not needed as it makes it much easier to have a layout that looks good in different window sizes.
Packit 1470ea
      Next, the box is added to the window.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
      

We need to define what happens when the user clicks on the button. GTK uses the concept of signals.

Packit 1470ea
      

Packit 1470ea
      When the <link href="http://valadoc.org/gtk+-3.0/Gtk.Button.html">button</link> is clicked, it fires the <link href="http://valadoc.org/gtk+-3.0/Gtk.Button.clicked.html">clicked</link> signal, which we can connect to some action (defined in a <link href="https://live.gnome.org/Vala/SignalsAndCallbacks">callback</link> method).
Packit 1470ea
      

Packit 1470ea
      

Packit 1470ea
      This is done using the connect method of the button's clicked signal, which in this case tells GTK to call the (yet undefined) on_image_open callback method when the button is clicked.
Packit 1470ea
      We will define the callback in the next section.
Packit 1470ea
      

Packit 1470ea
      

Packit 1470ea
      In the callback, we need to access the window and image widgets, which is why we defined them as private members at the top of our class.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
      

The last connect call makes sure that the application exits when the window is closed.

Packit 1470ea
      The code generated by Anjuta called an on_destroy callback method which called <link href="http://www.valadoc.org/gtk+-2.0/Gtk.main_quit.html">Gtk.main_quit</link>, but just connecting our signal to main_quit directly is easier. You can delete the on_destroy method.

Packit 1470ea
    </item>
Packit 1470ea
  </steps>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="image">
Packit 1470ea
  <title>Showing the image</title>
Packit 1470ea
  

We will now define the signal handler for the clicked signal for the

Packit 1470ea
button we mentioned before.
Packit 1470ea
  Add this code after the constructor:

Packit 1470ea
  
Packit 1470ea
public void on_open_image (Button self) {
Packit 1470ea
	var filter = new FileFilter ();
Packit 1470ea
	var dialog = new FileChooserDialog ("Open image",
Packit 1470ea
	                                    window,
Packit 1470ea
	                                    FileChooserAction.OPEN,
Packit 1470ea
	                                    Stock.OK,     ResponseType.ACCEPT,
Packit 1470ea
	                                    Stock.CANCEL, ResponseType.CANCEL);
Packit 1470ea
	filter.add_pixbuf_formats ();
Packit 1470ea
	dialog.add_filter (filter);
Packit 1470ea
Packit 1470ea
	switch (dialog.run ())
Packit 1470ea
	{
Packit 1470ea
		case ResponseType.ACCEPT:
Packit 1470ea
			var filename = dialog.get_filename ();
Packit 1470ea
			image.set_from_file (filename);
Packit 1470ea
			break;
Packit 1470ea
		default:
Packit 1470ea
			break;
Packit 1470ea
	}
Packit 1470ea
	dialog.destroy ();
Packit 1470ea
}
Packit 1470ea
]]>
Packit 1470ea
  

This is a bit complicated, so let's break it down:

Packit 1470ea
  <note>

A signal handler is a type of callback method that is called when a signal is emitted. Here the terms are used interchangeably.

</note>
Packit 1470ea
  <list>
Packit 1470ea
    <item>
Packit 1470ea
      

The first argument of the callback method is always the widget that sent the signal.

Packit 1470ea
      Sometimes other arguments related to the signal come after that, but clicked doesn't have any.

Packit 1470ea
      

In this case the button sent the clicked signal, which is connected to the on_open_image callback method:

Packit 1470ea
Packit 1470ea
        button.clicked.connect (on_open_image);
Packit 1470ea
]]>
Packit 1470ea
Packit 1470ea
  

The on_open_image method takes the button that emitted the signal as an argument:

Packit 1470ea
 
Packit 1470ea
        public void on_open_image (Button self)
Packit 1470ea
]]>
Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
      

The next interesting line is where the dialog for choosing the file is created.

Packit 1470ea
      <link href="http://www.valadoc.org/gtk+-3.0/Gtk.FileChooserDialog.html">FileChooserDialog</link>'s constructor takes the title of the dialog, the parent window of the dialog and several options like the number of buttons and their corresponding values.

Packit 1470ea
      

Notice that we are using <link href="http://unstable.valadoc.org/gtk+-3.0/Gtk.Stock.html">stock</link> button names from Gtk, instead of manually typing "Cancel" or "Open".

Packit 1470ea
      The advantage of using stock names is that the button labels will already be translated into the user's language.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
      

The next two lines restrict the <gui>Open</gui> dialog to only display files which can be opened by GtkImage. GtkImage is a widget which displays an image.

Packit 1470ea
      A filter object is created first; we then add all kinds of files supported by <link href="http://www.valadoc.org/gdk-pixbuf-2.0/Gdk.Pixbuf.html">Gdk.Pixbuf</link> (which includes most image formats like PNG and JPEG) to the filter.
Packit 1470ea
      Finally, we set this filter to be the <gui>Open</gui> dialog's filter.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
      

<link href="http://www.valadoc.org/gtk+-3.0/Gtk.Dialog.run.html">dialog.run</link> displays the <gui>Open</gui> dialog.

Packit 1470ea
      The dialog will wait for the user to choose an image; when they do, dialog.run will return the <link href="http://www.valadoc.org/gtk+-3.0/Gtk.ResponseType.html">ResponseType</link> value ResponseType.ACCEPT (it would return ResponseType.CANCEL if the user clicked <gui>Cancel</gui>).
Packit 1470ea
      The switch statement tests for this.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
      

Assuming that the user did click <gui>Open</gui>, the next lines get the filename of the image selected by the user, and tell the GtkImage widget to load and display the selected image.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
      

In the final line of this method, we destroy the <gui>Open</gui> dialog because we don't need it any more.

Packit 1470ea
      

Destroying automatically hides the dialog.

Packit 1470ea
    </item>
Packit 1470ea
  </list>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="run">
Packit 1470ea
  <title>Muntatge i execució de l'aplicació</title>
Packit 1470ea
  

All of the code should now be ready to go.

Packit 1470ea
  Click <guiseq><gui>Build</gui><gui>Build Project</gui></guiseq> to build everything again, and then <guiseq><gui>Run</gui><gui>Execute</gui></guiseq> to start the application.

Packit 1470ea
  

If you haven't already done so, choose the <file>src/image-viewer</file> application in the dialog that appears.

Packit 1470ea
  Finally, hit <gui>Run</gui> and enjoy!

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="impl">
Packit 1470ea
  <title>Implementació de referència</title>
Packit 1470ea
  

If you run into problems with the tutorial, compare your code with this <link href="image-viewer/image-viewer.vala">reference code</link>.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="next">
Packit 1470ea
  <title>Next steps</title>
Packit 1470ea
  

Here are some ideas for how you can extend this simple demonstration:

Packit 1470ea
  <list>
Packit 1470ea
  <item>

Set it up so that when the window opens it is of a specific size to start off with. For example, 200 X 200 pixels.

</item>
Packit 1470ea
   <item>
Packit 1470ea
     

Have the user select a directory rather than a file, and provide controls to cycle through all of the images in a directory.

Packit 1470ea
   </item>
Packit 1470ea
   <item>
Packit 1470ea
     

Apply random filters and effects to the image when it is loaded and allow the user to save the modified image.

Packit 1470ea
     

<link href="http://www.gegl.org/api.html">GEGL</link> provides powerful image manipulation capabilities.

Packit 1470ea
   </item>
Packit 1470ea
   <item>
Packit 1470ea
     

Allow the user to load images from network shares, scanners, and other more complicated sources.

Packit 1470ea
     

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.

Packit 1470ea
   </item>
Packit 1470ea
  </list>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
</page>