Lite mer än ett enkelt ”Hej världen”-program med GTKmm.
Dokumentationsprojekt för GNOME
gnome-doc-list@gnome.org
Johannes Schmid
jhs@gnome.org
Marta Maria Casetti
mmcasetti@gmail.com 2013
Sebastian Rasmussen
sebras@gmail.com 2019
Anders Jonsson
anders.jonsson@norsjovallen.se 2021

# Bildvisare

      I denna handledning kommer du lära dig:

        Några grundläggande koncept i C++/GObject-programmering
        Hur du skriver ett Gtk-program i C++

# Skapa ett projekt i Anjuta

Innan du börjar koda kommer du behöva konfigurera ett nytt projekt i Anjuta. Detta kommer skapa alla filer som du behöver för att bygga och köra koden senare. Det är också användbart för att hålla allting samlat.

Starta Anjuta och klicka på Arkiv Ny Projekt för att öppna projektguiden.

Välj GTKmm (enkel) från fliken C++, klicka på Framåt, och fyll i dina detaljer på de nästkommande sidorna. Använd image-viewer som projektnamn och katalog.

Säkerställ att Använd GtkBuilder för användargränssnitt är inaktiverat då vi kommer skapa användargränssnittet manuellt i denna handledning. Se handledningen Gitarrstämmare om du vill lära dig hur du använder gränssnittsbyggaren.

Klicka på Verkställ så kommer projektet skapas åt dig. Öppna src/main.cc från flikarna Projekt eller Filer. Du bör se kod som börjar med raderna:

#include <gtkmm.h> #include <iostream>

#include "config.h">

# Bygg koden för första gången

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.

`main`-funktionen skapar ett nytt (tomt) fönster och ställer in fönstertiteln.

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.

Denna kod är klar att användas, så du kan kompilera den genom att klicka på Bygg Bygg projekt (eller trycka Skift F7).

Press Execute on the next window that appears to configure a debug build. You only need to do this once, for the first build.

# Skapa användargränssnittet

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

int main (int argc, char *argv[]) { Gtk::Main kit(argc, argv);

Gtk::Window main_win; main_win.set_title ("image-viewer-cpp");

Gtk::Box* box = Gtk::manage(new Gtk::Box()); 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("Öppna bild…")); 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.

# Visa bilden

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

Gtk::Image* image = 0;

static void on_open_image () { Gtk::FileChooserDialog dialog("Open image", Gtk::FILE_CHOOSER_ACTION_OPEN); dialog.add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT); dialog.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);

Glib::RefPtr<Gtk::FileFilter> 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; } }

Det här är lite mer komplicerat än något som vi försökt så här långt, så låt oss dela upp det:

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.

Observera att vi använder standardknappnamn från Gtk, istället för att manuellt skriva in ”Avbryt” eller ”Öppna”. Fördelen med att använda standardnamn är att knappetiketterna redan kommer vara översatta till användarens språk.

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.

# Bygg och kör programmet

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

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

# Referensimplementation

Om du stöter på problem med handledningen kan du jämföra din kod med denna referenskod.

# Nästa steg

Här är några idéer på hur du kan utöka denna enkla demonstration:

Låt användaren välja en katalog snarare än en fil, och tillhandahåll kontroller för att gå igenom alla bilderna i en katalog.

Tillämpa slumpmässiga filter och effekter till bilden då den läses in och låt användaren spara den ändrade bilden.

GEGL har kraftfulla bildmanipuleringsförmågor.

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

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