Blame platform-demos/gl/image-viewer.c.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.c" xml:lang="gl">
Packit 1470ea
Packit 1470ea
  <info>
Packit 1470ea
    <title type="text">Image viewer (C)</title>
Packit 1470ea
    <link type="guide" xref="c#examples"/>
Packit 1470ea
Packit 1470ea
    <desc>Un pouco máis que un simple aplicativo Gtk «Ola mundo».</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>Proxecto de documentación de 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="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
  
Packit 1470ea
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
Packit 1470ea
      <mal:name>Fran Dieguez</mal:name>
Packit 1470ea
      <mal:email>frandieguez@gnome.org</mal:email>
Packit 1470ea
      <mal:years>2012-2013.</mal:years>
Packit 1470ea
    </mal:credit>
Packit 1470ea
  </info>
Packit 1470ea
Packit 1470ea
<title>Image viewer</title>
Packit 1470ea
Packit 1470ea
<synopsis>
Packit 1470ea
  

Neste titorial aprenderá:

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

Algúns conceptos básicos de programación de C/GObject

</item>
Packit 1470ea
    <item>

Como escribir un aplicativo GTK en C

</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>Cree un proxecto de Anjuta</title>
Packit 1470ea
  

Antes de comezar a programar, deberá configurar un proxecto novo en Anjuta. Isto creará todos os ficheiros que precise para construír e executar o código máis adiante. Tamén é útil para manter todo ordenado.

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

Inicie Anjuta e prema <guiseq><gui>Ficheiro</gui><gui>Novo</gui><gui>Proxecto</gui></guiseq> para abrir o asistente de proxectos.

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

Choose <gui>GTK+ (Simple)</gui> from the <gui>C</gui> tab, click <gui>Continue</gui>, and fill out your details on the next few pages. Use <file>image-viewer</file> as project name and directory.

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

Asegúrese que <gui>Usar GtkBuilder para a interface de usuario</gui> está desactivado xa que crearemos a UI manualmente neste titorial. Comprobe o titorial <link xref="guitar-tuner.c">Guitar-Tuner</link> se quere aprender como usar o construtor de interface.

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

Prema <gui>Aplicar</gui> para crear o proxecto. Abra <file>src/main.c</file> desde as lapelas <gui>Proxecto</gui> ou <gui>Ficheiro</gui>. Debería ver algún código que comeza coas liñas:

Packit 1470ea
    
Packit 1470ea
#include <config.h>
Packit 1470ea
#include <gtk/gtk.h>]]>
Packit 1470ea
    </item>
Packit 1470ea
  </steps>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="build">
Packit 1470ea
  <title>Construír o código por primeira vez</title>
Packit 1470ea
  

C is a rather verbose language, so don't be surprised that the file contains quite a lot of code. Most of it is template code. It loads an (empty) window and shows it. More details are given below; skip this list if you understand the basics:

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

The three #include lines at the top include the config (useful autoconf build defines), gtk (user interface) and gi18n (internationalization) libraries. Functions from these libraries are used in the rest of the code.

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

A función create_window crea unha xanela (baleira) nova e conecta un sinal para saír do aplicativo péchase esa xanela.

Packit 1470ea
    

Connecting signals is how you define what happens when you push a button, or when some other event happens. Here, the destroy function is called (and quits the app) when you close the window.

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

The main function is run by default when you start a C application. It calls a few functions which set up and then run the application. The gtk_main function starts the GTK main loop, which runs the user interface and starts listening for events (like clicks and key presses).

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

The ENABLE_NLS conditional definition sets up gettext, which is a framework for translating applications. These functions specify how translation tools should handle your app when you run them.

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
  

Prema <gui>Executar</gui> na seguinte xanela que aparece para configurar a compilación de depuración. Só precisa facer isto unha vez para a primeira compilación.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="ui">
Packit 1470ea
<title>Crear a interface de usuario</title>
Packit 1470ea

Now we will bring life into the empty window. GTK organizes the user interface

Packit 1470ea
with GtkContainers that can contain other widgets and even other containers. Here we
Packit 1470ea
will use the simplest available container, a GtkBox:

Packit 1470ea
Packit 1470ea
static GtkWidget*
Packit 1470ea
create_window (void)
Packit 1470ea
{
Packit 1470ea
	GtkWidget *window;
Packit 1470ea
	GtkWidget *button;
Packit 1470ea
	GtkWidget *image;
Packit 1470ea
	GtkWidget *box;
Packit 1470ea
Packit 1470ea
	/* Set up the UI */
Packit 1470ea
	window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
Packit 1470ea
	gtk_window_set_title (GTK_WINDOW (window), "image-viewer-c");
Packit 1470ea
Packit 1470ea
	box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
Packit 1470ea
	button = gtk_button_new_with_label (_("Open image"));
Packit 1470ea
	image = gtk_image_new ();
Packit 1470ea
Packit 1470ea
	gtk_box_pack_start (GTK_BOX (box), image, TRUE, TRUE, 0);
Packit 1470ea
	gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
Packit 1470ea
Packit 1470ea
	gtk_container_add (GTK_CONTAINER (window), box);
Packit 1470ea
Packit 1470ea
	/* Connect signals */
Packit 1470ea
Packit 1470ea
	/* Show open dialog when opening a file */
Packit 1470ea
	g_signal_connect (button, "clicked", G_CALLBACK (on_open_image), image);
Packit 1470ea
Packit 1470ea
	/* Exit when the window is closed */
Packit 1470ea
	g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
Packit 1470ea
Packit 1470ea
	return window;
Packit 1470ea
}
Packit 1470ea
]]>
Packit 1470ea
  <steps>
Packit 1470ea
    <item>
Packit 1470ea
    

The first lines create the widgets we want to use: a button for opening up an image, the image view widget itself and

Packit 1470ea
    the box we will use as a container. The macros like GTK_BOX are used for dynamic type checking and casting
Packit 1470ea
    which is needed as C doesn't support object-orientation out-of-the-box.

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

The calls to gtk_box_pack_start add the two widgets to the box and define their behaviour. The image will

Packit 1470ea
    expand into any available space while the button will just be as big as needed. You will notice that we don't set
Packit 1470ea
    explicit sizes on the widgets. In GTK this is usually not needed as it makes it much easier to have a layout that
Packit 1470ea
    looks good in different window sizes. 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. When the button is clicked, it fires the clicked signal, which we can connect to some action. This is done using the g_signal_connect

Packit 1470ea
    function which tells GTK to call the on_image_open function when the button is clicked and
Packit 1470ea
    to pass the image as an additional argument to that function. We will define the callback in the next section.

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

The last g_signal_connect() makes sure that the application exits when the window is closed.

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

As a last step, make sure to replace the gtk_widget_show call in the main() function by

Packit 1470ea
    gtk_widget_show_all() to show the window and all the widgets it contains.

Packit 1470ea
    </item>
Packit 1470ea
  </steps>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="image">
Packit 1470ea
<title>Mostrar a imaxe</title>
Packit 1470ea

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

Packit 1470ea
button we mentioned before. Add this code before the create_window()
Packit 1470ea
method.

Packit 1470ea
Packit 1470ea
static void
Packit 1470ea
on_open_image (GtkButton* button, gpointer user_data)
Packit 1470ea
{
Packit 1470ea
	GtkWidget *image = GTK_WIDGET (user_data);
Packit 1470ea
	GtkWidget *toplevel = gtk_widget_get_toplevel (image);
Packit 1470ea
	GtkFileFilter *filter = gtk_file_filter_new ();
Packit 1470ea
	GtkWidget *dialog = gtk_file_chooser_dialog_new (_("Open image"),
Packit 1470ea
	                                                 GTK_WINDOW (toplevel),
Packit 1470ea
	                                                 GTK_FILE_CHOOSER_ACTION_OPEN,
Packit 1470ea
	                                                 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
Packit 1470ea
	                                                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
Packit 1470ea
	                                                 NULL);
Packit 1470ea
Packit 1470ea
	gtk_file_filter_add_pixbuf_formats (filter);
Packit 1470ea
	gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog),
Packit 1470ea
	                             filter);
Packit 1470ea
Packit 1470ea
	switch (gtk_dialog_run (GTK_DIALOG (dialog)))
Packit 1470ea
	{
Packit 1470ea
		case GTK_RESPONSE_ACCEPT:
Packit 1470ea
		{
Packit 1470ea
			gchar *filename =
Packit 1470ea
				gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
Packit 1470ea
			gtk_image_set_from_file (GTK_IMAGE (image), filename);
Packit 1470ea
			break;
Packit 1470ea
		}
Packit 1470ea
		default:
Packit 1470ea
			break;
Packit 1470ea
	}
Packit 1470ea
	gtk_widget_destroy (dialog);
Packit 1470ea
}
Packit 1470ea
]]>
Packit 1470ea
  

This is a bit more complicated than anything we've attempted so far, so let's break it down:

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

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

Packit 1470ea
    other arguments related to the signal come after that, but clicked doesn't have any. Next is
Packit 1470ea
    the user_data argument which is a pointer to the data we passed when connecting the signal.
Packit 1470ea
    In this case it is our GtkImage object.

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

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

Packit 1470ea
      gtk_file_chooser_dialog_new. The function takes the title of the dialog, the
Packit 1470ea
      parent window of the dialog and several options like the number of buttons and their corresponding
Packit 1470ea
      values.

Packit 1470ea
    

Notice that we are using stock button names from Gtk, instead of manually typing "Cancel" or "Open". 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. A filter object is created first; we then add all kinds of files supported by GdkPixbuf (which includes most image formats like PNG and JPEG) to the filter. Finally, we set this filter to be the <gui>Open</gui> dialog's filter.

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

gtk_dialog_run displays the <gui>Open</gui> dialog. The dialog will wait for the user to choose an image; when they do, gtk_dialog_run will return the value GTK_RESPONSE_ACCEPT (it would return GTK_RESPONSE_CANCEL if the user clicked <gui>Cancel</gui>). The switch statement tests for this.

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

Assuming that the user did click <gui>Open</gui>, the next line sets the file property of the GtkImage to the filename of the image selected by the user. The GtkImage will then load and display the chosen 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>Construír e executar o aplicativo</title>
Packit 1470ea
  

All of the code should now be ready to go. 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
  

Se non o fixo aínda, seleccione o aplicativo <file>Debug/src/image-viewer</file> no diálogo que aparece. Finalmente, prema <gui>Executar</gui> e desfrute!

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="impl">
Packit 1470ea
 <title>Implementación de referencia</title>
Packit 1470ea
 

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

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="next">
Packit 1470ea
  <title>Seguintes pasos</title>
Packit 1470ea
  

Aquí hai algunhas ideas sobre como pode estender esta sinxela demostración:

Packit 1470ea
  <list>
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
   

Aplicar filtros aleatorios e efectos á imaxe cando se carga e permitir ao usuario gardar a imaxe modificada.

Packit 1470ea
   

<link href="http://www.gegl.org/api.html">GEGL</link> fornece capacidades moi potentes de manipulación de imaxes.

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

Permitir ao usuario cargar imaxes desde recursos de rede compartidos, escáneres e outras fontes máis complicadas.

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
Packit 1470ea
</page>