Blame platform-demos/de/image-viewer.cpp.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.cpp" xml:lang="de">
Packit 1470ea
Packit 1470ea
  <info>
Packit 1470ea
    <link type="guide" xref="cpp#examples"/>
Packit 1470ea
Packit 1470ea
    <desc>A little bit more than a simple "Hello world" GTKmm 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-Dokumentationsprojekt</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>Mario Blättermann</mal:name>
Packit 1470ea
      <mal:email>mario.blaettermann@gmail.com</mal:email>
Packit 1470ea
      <mal:years>2011, 2013</mal:years>
Packit 1470ea
    </mal:credit>
Packit 1470ea
  </info>
Packit 1470ea
Packit 1470ea
<title>Bildbetrachter</title>
Packit 1470ea
Packit 1470ea
<synopsis>
Packit 1470ea
  

In diesem Tutorial lernen Sie, wie:

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

Some basic concepts of C++/GObject programming

</item>
Packit 1470ea
    <item>

Schreiben einer Gtk-Anwendung 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>Erstellen eines Projekts 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>GTKmm (Simple)</gui> from the <gui>C++</gui> tab, click <gui>Forward</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.cpp">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.cc</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 <gtkmm.h>
Packit 1470ea
#include <iostream>
Packit 1470ea
Packit 1470ea
#include "config.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
  

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

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

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.

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

The main function creates a new (empty) window and sets the window title.

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

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

Packit 1470ea
    as an argument to that function, the application will automatically exit when
Packit 1470ea
    that window is closed.

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>Erstellen der Benutzeroberfläche</title>
Packit 1470ea

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

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

Packit 1470ea
Packit 1470ea
int
Packit 1470ea
main (int argc, char *argv[])
Packit 1470ea
{
Packit 1470ea
	Gtk::Main kit(argc, argv);
Packit 1470ea
Packit 1470ea
	Gtk::Window main_win;
Packit 1470ea
	main_win.set_title ("image-viewer-cpp");
Packit 1470ea
Packit 1470ea
	Gtk::Box* box = Gtk::manage(new Gtk::Box());
Packit 1470ea
	box->set_orientation (Gtk::ORIENTATION_VERTICAL);
Packit 1470ea
	box->set_spacing(6);
Packit 1470ea
	main_win.add(*box);
Packit 1470ea
Packit 1470ea
	image = Gtk::manage(new Gtk::Image());
Packit 1470ea
	box->pack_start (*image, true, true);
Packit 1470ea
Packit 1470ea
	Gtk::Button* button = Gtk::manage(new Gtk::Button("Open Image…"));
Packit 1470ea
	button->signal_clicked().connect (
Packit 1470ea
		sigc::ptr_fun(&on_open_image));
Packit 1470ea
	box->pack_start (*button, false, false);
Packit 1470ea
Packit 1470ea
	main_win.show_all_children();
Packit 1470ea
	kit.run(main_win);
Packit 1470ea
Packit 1470ea
	return 0;
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 the box we will use as a container.

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

The calls to 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 GTKmm 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. 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

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

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

The last step is to show all widgets in the window using

Packit 1470ea
    show_all_children(). This is equivalent to using the show()
Packit 1470ea
    method on all our child widgets.

Packit 1470ea
    </item>
Packit 1470ea
  </steps>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="show">
Packit 1470ea
<title>Bildanzeige</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 main
Packit 1470ea
method.

Packit 1470ea
Packit 1470ea
Gtk::Image* image = 0;
Packit 1470ea
Packit 1470ea
static void
Packit 1470ea
on_open_image ()
Packit 1470ea
{
Packit 1470ea
	Gtk::FileChooserDialog dialog("Open image",
Packit 1470ea
	                              Gtk::FILE_CHOOSER_ACTION_OPEN);
Packit 1470ea
	dialog.add_button (Gtk::Stock::OPEN,
Packit 1470ea
	                   Gtk::RESPONSE_ACCEPT);
Packit 1470ea
	dialog.add_button (Gtk::Stock::CANCEL,
Packit 1470ea
	                   Gtk::RESPONSE_CANCEL);
Packit 1470ea
Packit 1470ea
	Glib::RefPtr<Gtk::FileFilter> filter =
Packit 1470ea
		Gtk::FileFilter::create();
Packit 1470ea
	filter->add_pixbuf_formats();
Packit 1470ea
	filter->set_name("Images");
Packit 1470ea
	dialog.add_filter (filter);
Packit 1470ea
Packit 1470ea
	const int response = dialog.run();
Packit 1470ea
	dialog.hide();
Packit 1470ea
Packit 1470ea
	switch (response)
Packit 1470ea
	{
Packit 1470ea
		case Gtk::RESPONSE_ACCEPT:
Packit 1470ea
			image->set(dialog.get_filename());
Packit 1470ea
			break;
Packit 1470ea
		default:
Packit 1470ea
			break;
Packit 1470ea
	}
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>
Packit 1470ea
      

The dialog for choosing the file is created using the

Packit 1470ea
      Gtk::FileChooserDialog constructor. This takes the title and type of the dialog. In our case, it is an Open dialog.

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

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

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
    

The second argument to the add_button() method is a value to identify

Packit 1470ea
    the clicked button. We use predefined values provided by GTKmm here, too.
Packit 1470ea
    

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 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 <gui>Open</gui> dialog's filter.

Packit 1470ea
    

Glib::RefPtr is a smart pointer used here, that makes sure that the filter is

Packit 1470ea
    destroyed when there is no reference to it anymore.

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

dialog.run displays the <gui>Open</gui> 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 <gui>Cancel</gui>). The switch statement tests for this.

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

We hide the <gui>Open</gui> 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

Packit 1470ea
    destroyed (and therefore hidden) when the scope ends.

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

Assuming that the user did click <gui>Open</gui>, the next line loads the

Packit 1470ea
    file into the Gtk::Image so that it is displayed.

Packit 1470ea
    </item>
Packit 1470ea
  </list>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="build2">
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>Referenz-Implementierung</title>
Packit 1470ea
 

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

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="next">
Packit 1470ea
  <title>Nächste Schritte</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>