<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" type="topic" id="image-viewer.vala" xml:lang="sv">

  <info>
  <title type="text">Bildvisare (Vala)</title>
    <link type="guide" xref="vala#examples"/>

    <desc>Lite mer än ett enkelt ”Hej världen”-program i GTK+.</desc>

    <revision pkgversion="0.1" version="0.1" date="2011-03-18" status="review"/>
    <credit type="author">
      <name>Dokumentationsprojekt för GNOME</name>
      <email its:translate="no">gnome-doc-list@gnome.org</email>
    </credit>
    <credit type="author">
      <name>Johannes Schmid</name>
      <email its:translate="no">jhs@gnome.org</email>
    </credit>
    <credit type="author">
      <name>Philip Chimento</name>
      <email its:translate="no">philip.chimento@gmail.com</email>
    </credit>
    <credit type="editor">
     <name>Tiffany Antopolski</name>
     <email its:translate="no">tiffany.antopolski@gmail.com</email>
    </credit>
  <credit type="editor">
    <name>Marta Maria Casetti</name>
    <email its:translate="no">mmcasetti@gmail.com</email>
    <years>2013</years>
  </credit>
  
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
      <mal:name>Sebastian Rasmussen</mal:name>
      <mal:email>sebras@gmail.com</mal:email>
      <mal:years>2019</mal:years>
    </mal:credit>
  
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
      <mal:name>Anders Jonsson</mal:name>
      <mal:email>anders.jonsson@norsjovallen.se</mal:email>
      <mal:years>2021</mal:years>
    </mal:credit>
  </info>

<title>Bildvisare</title>
<synopsis>
  <p>I denna handledning kommer du skapa ett program som öppnar och visar en bildfil. Du kommer att lära dig:</p>
  <list type="numbered">
    <item><p>Hur du konfigurerar ett grundläggande projekt med den <link xref="getting-ready">integrerade utvecklingsmiljön Anjuta</link>.</p></item>
    <item><p>Hur du skriver ett <link href="http://developer.gnome.org/platform-overview/stable/gtk">Gtk-program</link> i Vala</p></item>
    <item><p>Några grundläggande koncept i <link href="http://developer.gnome.org/gobject/stable/">GObject</link>-programmering</p></item>

  </list>
  <p>Du behöver följande för att kunna följa denna handledning:</p>
  <list>
    <item><p>Grundläggande kunskap i programmeringsspråket <link href="https://live.gnome.org/Vala/Tutorial">Vala</link>.</p></item>
    <item><p>En installerad kopia av <app>Anjuta</app>.</p></item>
    <item><p>Du kan finna API-referensen för <link href="http://valadoc.org/gtk+-3.0/">gtk+-3.0</link> användbar, även om det inte är nödvändigt att följa handledningen.</p></item>
  </list>
</synopsis>

<media type="image" mime="image/png" src="media/image-viewer.png"/>

<section id="anjuta">
  <title>Skapa ett projekt i Anjuta</title>
  <p>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.</p>
  <steps>
    <item>
      <p>Starta <app>Anjuta</app> och klicka på <gui>Skapa ett nytt projekt</gui> eller <guiseq><gui>Arkiv</gui><gui>Ny</gui><gui>Projekt</gui></guiseq> för att öppna projektguiden.</p>
    </item>
    <item>
      <p>Välj <gui>GTK+ (enkel)</gui> från fliken <gui>Vala</gui>, klicka på <gui>Fortsätt</gui>, och fyll i dina detaljer på de nästkommande sidorna. Använd <file>image-viewer</file> som projektnamn och katalog.</p>
   	</item>
    <item>
      <p>Säkerställ att <gui>Använd GtkBuilder för användargränssnitt</gui> inte är ikryssad då vi kommer skapa användargränssnittet manuellt i denna handledning.</p>
     <note><p>Du kommer lära dig hur du använder gränssnittsbyggaren i handledningen <link xref="guitar-tuner.vala">Gitarrstämmare</link>.</p></note>
    </item>
    <item>
      <p>Klicka på <gui>Fortsätt</gui> sedan <gui>Verkställ</gui> så kommer projektet skapas åt dig. Öppna <file>src/image_viewer.vala</file> från flikarna <gui>Projekt</gui> eller <gui>Filer</gui>. Du kommer se denna kod:</p>
      <code mime="text/x-csharp">
using GLib;
using Gtk;

public class Main : Object
{

	public Main ()
	{
		Window window = new Window();
		window.set_title ("Hej världen");
		window.show_all();
		window.destroy.connect(on_destroy);
	}

	public void on_destroy (Widget window)
	{
		Gtk.main_quit();
	}

	static int main (string[] args)
	{
		Gtk.init (ref args);
		var app = new Main ();

		Gtk.main ();

		return 0;
	}
}</code>
    </item>
  </steps>
</section>

<section id="build">
  <title>Bygg koden för första gången</title>
  <p>The code loads an (empty) window from the user interface description file and shows it.
  More details are given below; skip this list if you understand the basics:</p>

  <list>
    <item>
      <p>The two <code>using</code> lines at the top import namespaces so we don't have to name them explicitly.</p>
    </item>
    <item>
      <p>The constructor of the <code>Main</code> class creates a new (empty) window and connects a <link href="https://live.gnome.org/Vala/SignalsAndCallbacks">signal</link> to exit the application when that window is closed.</p>
      <p>Connecting signals is how you define what happens when you push a button, or when some other event happens.
      Here, the <code>destroy</code> function is called (and quits the app) when you close the window.</p>
    </item>
    <item>
      <p>The <code>static main</code> function is run by default when you start a Vala application.
      It calls a few functions which create the <code>Main</code> class, set up and then run the application.
      The <link href="http://valadoc.org/gtk+-3.0/Gtk.main.html"><code>Gtk.main</code></link> function starts the GTK <link href="http://en.wikipedia.org/wiki/Event_loop">main loop</link>, which runs the user interface and starts listening for events (like clicks and key presses).</p>
    </item>
  </list>

  <p>Denna kod är klar att användas, så du kan kompilera den genom att klicka på <guiseq><gui>Bygg</gui><gui>Bygg projekt</gui></guiseq> (eller trycka <keyseq><key>Skift</key><key>F7</key></keyseq>).</p>
  <p>Change the <gui>Configuration</gui> to <gui>Default</gui> and then press <gui>Execute</gui> to configure the build directory.
  You only need to do this once, for the first build.</p>
</section>

<section id="ui">
  <title>Skapa användargränssnittet</title>
  <p>Now we will bring life into the empty window.
  GTK organizes the user interface with <link href="http://www.valadoc.org/gtk+-2.0/Gtk.Container.html"><code>Gtk.Container</code></link>s that can contain other widgets and even other containers.
  Here we will use the simplest available container, a <link href="http://unstable.valadoc.org/gtk+-2.0/Gtk.Box.html"><code>Gtk.Box</code></link>.</p>

<p>Add the following lines to the top of the <code>Main</code> class:</p>
  <code mime="text/x-csharp">
private Window window;
private Image image;
</code>

<p>Ersätt nu den aktuella konstruktorn med den nedan:</p>
<code mime="text/x-csharp">

public Main () {

	window = new Window ();
	window.set_title ("Bildvisare i Vala");

	// Konfigurera användargränssnittet
	var box = new Box (Orientation.VERTICAL, 5);
	var button = new Button.with_label ("Öppna bild");
	image = new Image ();

	box.pack_start (image, true, true, 0);
	box.pack_start (button, false, false, 0);
	window.add (box);

	// Visa öppna-dialog när en fil öppnas
	button.clicked.connect (on_open_image);

	window.show_all ();
	window.destroy.connect (main_quit);
}
</code>
  <steps>
    <item>
      <p>The first two lines are the parts of the GUI that we will need to access from more than one method.
      We declare them up here so that they are accessible throughout the class instead of only in the method where they are created.</p>
    </item>
    <item>
      <p>The first lines of the constructor create the empty window.
      The next 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.</p>
    </item>
    <item>
      <p>The calls to <link href="http://unstable.valadoc.org/gtk+-2.0/Gtk.Box.pack_start.html"><code>pack_start</code></link> add the two widgets to the box and define their behaviour.
      The image will expand into any available space whereas the button will just be as big as needed.
      You will notice that we don't set explicit sizes on the widgets.
      In GTK 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.</p>
    </item>
    <item>
      <p>We need to define what happens when the user clicks on the button. GTK uses the concept of <em>signals</em>.</p>
      <p>
      When the <link href="http://valadoc.org/gtk+-3.0/Gtk.Button.html">button</link> is clicked, it fires the <link href="http://valadoc.org/gtk+-3.0/Gtk.Button.clicked.html"><code>clicked</code></link> signal, which we can connect to some action (defined in a <link href="https://live.gnome.org/Vala/SignalsAndCallbacks">callback</link> method).
      </p>
      <p>
      This is done using the <code>connect</code> method of the button's <code>clicked</code> signal, which in this case tells GTK to call the (yet undefined) <code>on_image_open</code> callback method when the button is clicked.
      We will define the <em>callback</em> in the next section.
      </p>
      <p>
      In the callback, we need to access the <code>window</code> and <code>image</code> widgets, which is why we defined them as private members at the top of our class.</p>
    </item>
    <item>
      <p>The last <code>connect</code> call makes sure that the application exits when the window is closed.
      The code generated by Anjuta called an <code>on_destroy</code> callback method which called <link href="http://www.valadoc.org/gtk+-2.0/Gtk.main_quit.html"><code>Gtk.main_quit</code></link>, but just connecting our signal to <code>main_quit</code> directly is easier. You can delete the <code>on_destroy</code> method.</p>
    </item>
  </steps>
</section>

<section id="image">
  <title>Visa bilden</title>
  <p>We will now define the signal handler for the <code>clicked</code> signal for the
button we mentioned before.
  Add this code after the constructor:</p>
  <code mime="text/x-csharp"><![CDATA[
public void on_open_image (Button self) {
	var filter = new FileFilter ();
	var dialog = new FileChooserDialog ("Open image",
	                                    window,
	                                    FileChooserAction.OPEN,
	                                    Stock.OK,     ResponseType.ACCEPT,
	                                    Stock.CANCEL, ResponseType.CANCEL);
	filter.add_pixbuf_formats ();
	dialog.add_filter (filter);

	switch (dialog.run ())
	{
		case ResponseType.ACCEPT:
			var filename = dialog.get_filename ();
			image.set_from_file (filename);
			break;
		default:
			break;
	}
	dialog.destroy ();
}
]]></code>
  <p>This is a bit complicated, so let's break it down:</p>
  <note><p>A signal handler is a type of callback method that is called when a signal is emitted.  Here the terms are used interchangeably.</p></note>
  <list>
    <item>
      <p>The first argument of the callback method is always the widget that sent the signal.
      Sometimes other arguments related to the signal come after that, but <em>clicked</em> doesn't have any.</p>
      <p>In this case the <code>button</code> sent the <code>clicked</code> signal, which is connected to the <code>on_open_image</code> callback method:</p>
<code mime="text/x-csharp">
        button.clicked.connect (on_open_image);
</code>

  <p>The <code>on_open_image</code> method takes the button that emitted the signal as an argument:   </p>
 <code mime="text/x-csharp"><![CDATA[
        public void on_open_image (Button self)
]]></code>
    </item>
    <item>
      <p>The next interesting line is where the dialog for choosing the file is created.
      <link href="http://www.valadoc.org/gtk+-3.0/Gtk.FileChooserDialog.html"><code>FileChooserDialog</code></link>'s constructor takes the title of the dialog, the parent window of the dialog and several options like the number of buttons and their corresponding values.</p>
      <p>Notice that we are using <link href="http://unstable.valadoc.org/gtk+-3.0/Gtk.Stock.html"><em>stock</em></link> 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.</p>
    </item>
    <item>
      <p>The next two lines restrict the <gui>Open</gui> dialog to only display files which can be opened by <em>GtkImage</em>. GtkImage is a widget which displays an image.
      A filter object is created first; we then add all kinds of files supported by <link href="http://www.valadoc.org/gdk-pixbuf-2.0/Gdk.Pixbuf.html"><code>Gdk.Pixbuf</code></link> (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.</p>
    </item>
    <item>
      <p><link href="http://www.valadoc.org/gtk+-3.0/Gtk.Dialog.run.html"><code>dialog.run</code></link> displays the <gui>Open</gui> dialog.
      The dialog will wait for the user to choose an image; when they do, <code>dialog.run</code> will return the <link href="http://www.valadoc.org/gtk+-3.0/Gtk.ResponseType.html">ResponseType</link> value <code>ResponseType.ACCEPT</code> (it would return <code>ResponseType.CANCEL</code> if the user clicked <gui>Cancel</gui>).
      The <code>switch</code> statement tests for this.</p>
    </item>
    <item>
      <p>Assuming that the user did click <gui>Open</gui>, the next lines get the filename of the image selected by the user, and tell the <code>GtkImage</code> widget to load and display the selected image.</p>
    </item>
    <item>
      <p>In the final line of this method, we destroy the <gui>Open</gui> dialog because we don't need it any more.</p>
      <p>Destroying automatically hides the dialog.</p>
    </item>
  </list>
</section>

<section id="run">
  <title>Bygg och kör programmet</title>
  <p>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.</p>
  <p>If you haven't already done so, choose the <file>src/image-viewer</file> application in the dialog that appears.
  Finally, hit <gui>Run</gui> and enjoy!</p>
</section>

<section id="impl">
  <title>Referensimplementation</title>
  <p>Om du stöter på problem med handledningen kan du jämföra din kod med denna <link href="image-viewer/image-viewer.vala">referenskod</link>.</p>
</section>

<section id="next">
  <title>Nästa steg</title>
  <p>Här är några idéer på hur du kan utöka denna enkla demonstration:</p>
  <list>
  <item><p>Set it up so that when the window opens it is of a specific size to start off with. For example, 200 X 200 pixels.</p></item>
   <item>
     <p>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.</p>
   </item>
   <item>
     <p>Tillämpa slumpmässiga filter och effekter till bilden då den läses in och låt användaren spara den ändrade bilden.</p>
     <p><link href="http://www.gegl.org/api.html">GEGL</link> har kraftfulla bildmanipuleringsförmågor.</p>
   </item>
   <item>
     <p>Allow the user to load images from network shares, scanners, and other more complicated sources.</p>
     <p>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.</p>
   </item>
  </list>
</section>

</page>
