Blame platform-demos/pt_BR/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="pt-BR">
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>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>GNOME Documentation Project</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>Rafael Ferreira</mal:name>
Packit 1470ea
      <mal:email>rafael.f.f1@gmail.com</mal:email>
Packit 1470ea
      <mal:years>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
  

In this tutorial, you will learn:

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

Some basic concepts of C/GObject programming

</item>
Packit 1470ea
    <item>

How to write a Gtk application in 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>Create a project in Anjuta</title>
Packit 1470ea
  

Before you start coding, you'll need to set up a new project in Anjuta. This will create all of the files you need to build and run the code later on. It's also useful for keeping everything together.

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

Start Anjuta and click <guiseq><gui>File</gui><gui>New</gui><gui>Project</gui></guiseq> to open the project wizard.

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
    

Make sure that <gui>Use GtkBuilder for user interface</gui> is disabled as we will

Packit 1470ea
    create the UI manually in this tutorial. Check the <link xref="guitar-tuner.c">Guitar-Tuner</link>
Packit 1470ea
    tutorial if you want to learn how to use the interface builder.

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

Click <gui>Apply</gui> and the project will be created for you. Open <file>src/main.c</file> from the <gui>Project</gui> or <gui>File</gui> tabs. You should see some code which starts with the lines:

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>Build the code for the first time</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
    

The create_window function creates a new (empty) window and connects a signal 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. 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
  

Press <gui>Execute</gui> on the next window that appears to configure a debug build. 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. 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>Showing the image</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>Build and run the application</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
  

If you haven't already done so, choose the <file>Debug/src/image-viewer</file> application in the dialog that appears. Finally, hit <gui>Run</gui> and enjoy!

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="impl">
Packit 1470ea
 <title>Reference Implementation</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>Next steps</title>
Packit 1470ea
  

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

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
   

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