Un pouco máis que un simple aplicativo Gtkmm «Ola mundo». Proxecto de documentación de GNOME gnome-doc-list@gnome.org Johannes Schmid jhs@gnome.org Marta Maria Casetti mmcasetti@gmail.com 2013 Fran Dieguez frandieguez@gnome.org 2012-2013. Image viewer

Neste titorial aprenderá:

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

Cómo escribir un aplicativo GTK en C++

Cree un proxecto de Anjuta

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.

Inicie Anjuta e prema FicheiroNovoProxecto para abrir o asistente de proxectos.

Seleccione GTK+ (Simple) desde a lapela C++, prema Adiante e complete os detalles nas seguintes páxinas. Use image-viewer como nome do proxecto e cartafol.

Asegúrese que Usar GtkBuilder para a interface de usuario está desactivado xa que crearemos a UI manualmente neste titorial. Comprobe o titorial Guitar-Tuner se quere aprender como usar o construtor de interface.

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

#include #include "config.h">]]>
Construír o código por primeira vez

This is a very basic C++ code setting up GTKmm. More details are given below; skip this list if you understand the basics:

The three #include lines at the top include the config (useful autoconf build defines), gtkmm (user interface) and iostream (C++-STL) libraries. Functions from these libraries are used in the rest of the code.

A función main crea unha xanela nova (e baleira) e estabelece o título da xanela.

The kit::run() call starts the GTKmm main loop, which runs the user interface and starts listening for events (like clicks and key presses). As we give the window as an argument to that function, the application will automatically exit when that window is closed.

This code is ready to be used, so you can compile it by clicking BuildBuild Project (or press ShiftF7).

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

Crear a interface de usuario

Now we will bring life into the empty window. GTKmm organizes the user interface with Gtk::Containers that can contain other widgets and even other containers. Here we will use the simplest available container, a Gtk::Box:

set_orientation (Gtk::ORIENTATION_VERTICAL); box->set_spacing(6); main_win.add(*box); image = Gtk::manage(new Gtk::Image()); box->pack_start (*image, true, true); Gtk::Button* button = Gtk::manage(new Gtk::Button("Open Image…")); button->signal_clicked().connect ( sigc::ptr_fun(&on_open_image)); box->pack_start (*button, false, false); main_win.show_all_children(); kit.run(main_win); return 0; } ]]>

The first 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.

The calls to pack_start add the two widgets to the box and define their behaviour. The image will expand into any available space while the button will just be as big as needed. You will notice that we don't set explicit sizes on the widgets. In GTKmm this is usually not needed as it makes it much easier to have a layout that looks good in different window sizes. Next, the box is added to the window.

We need to define what happens when the user clicks on the button. GTKmm 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 signal_clicked().connect method which tells GTKmm to call the on_open_image function when the button is clicked. We will define the callback in the next section.

The last step is to show all widgets in the window using show_all_children(). This is equivalent to using the show() method on all our child widgets.

Mostrar a imaxe

We will now define the signal handler for the clicked signal or the button we mentioned before. Add this code before the main method.

filter = Gtk::FileFilter::create(); filter->add_pixbuf_formats(); filter->set_name("Images"); dialog.add_filter (filter); const int response = dialog.run(); dialog.hide(); switch (response) { case Gtk::RESPONSE_ACCEPT: image->set(dialog.get_filename()); break; default: break; } } ]]>

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

The dialog for choosing the file is created using the Gtk::FileChooserDialog constructor. This takes the title and type of the dialog. In our case, it is an Open dialog.

The next two lines add an Open and a Close button to the dialog.

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.

The second argument to the add_button() method is a value to identify the clicked button. We use predefined values provided by GTKmm here, too.

The next two lines restrict the Open dialog to only display files which can be opened by Gtk::Image. A filter object is created first; we then add all kinds of files supported by Gdk::Pixbuf (which includes most image formats like PNG and JPEG) to the filter. Finally, we set this filter to be the Open dialog's filter.

Glib::RefPtr is a smart pointer used here, that makes sure that the filter is destroyed when there is no reference to it anymore.

dialog.run displays the Open dialog. The dialog will wait for the user to choose an image; when they do, dialog.run will return the value Gtk::RESPONSE_ACCEPT (it would return Gtk::RESPONSE_CANCEL if the user clicked Cancel). The switch statement tests for this.

We hide the Open dialog because we don't need it any more. The dialog would be hidden later anyway, as it is only a local variable and is destroyed (and therefore hidden) when the scope ends.

Assuming that the user did click Open, the next line loads the file into the Gtk::Image so that it is displayed.

Construír e executar o aplicativo

All of the code should now be ready to go. Click BuildBuild Project to build everything again, and then RunExecute to start the application.

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

Implementación de referencia

Se ten problemas con este titorial, compare o seu código con este código de referencia.

Seguintes pasos

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

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

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

GEGL fornece capacidades moi potentes de manipulación de imaxes.

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

You can use GIO to handle network file transfers and the like, and GNOME Scan to handle scanning.