V této lekci vytvoříte aplikaci, která otevře a zobrazí soubor s obrázkem. Naučíte se:
Jak vytvořit základní projekt pomocí IDE Anjuta.
Jak napsat aplikaci Gtk v jazyce Vala.
Některé základní koncepty programování s GObject
Abyste mohli pokračovat v této lekci, budete potřebovat následující:
Základní znalosti programovacího jazyka Vala.
Nainstalovanou kopii vývojářského studia
Může se vám hodit referenční příručka k API gtk+-3.0, ačkoliv pro tuto výuku není nutná.
Než začnete s kódováním, musíte ve studiu Anjuta vytvořit nový projekt. Tím se vytvoří všechny soubory, které budete později potřebovat k sestavení a spuštění kódu. Je to také užitečné kvůli udržení všeho pohromadě.
Spusťte aplikaci
Na kartě
Ujistěte se, že
Jak používat builder k tvorbě rozhraní se můžete naučit v lekci Kytarová ladička.
Klikněte na
using GLib;
using Gtk;
public class Main : Object
{
public Main ()
{
Window window = new Window();
window.set_title ("Hello World");
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;
}
}
Kód načte (prázdné) okno ze souboru s popisem uživatelského rozhraní a zobrazí jej. Dále to podrobněji rozebereme. Pokud jste již pochopili základy, tak tento seznam můžete přeskočit:
Dva řádky using
v horní části naimportují jmenné prostory, abychom je nemuseli výslovně uvádět.
Konstruktor třídy Main
vytvoří nové (prázdné) okno a napojí signál, aby se aplikace ukončila, když se zavře okno.
Napojení signálu je způsob, jak definovat, co se má stát, když zmáčknete tlačítko nebo se prostě něco přihodí. Zde je zavolána metoda destroy
(a ukončení aplikace) při zavření okna.
Funkce static main
se spustí jako výchozí, když spustíte aplikaci napsanou v jazyce Vala. Volá pár funkcí, které vytvoří třídu Main
a nastaví a spustí aplikaci. Funkce Gtk.main
spustí hlavní smyčku GTK, která spustí uživatelské rozhraní a začne naslouchat událostem (jako je kliknutí nebo zmáčknutí klávesy).
Kód je připravený k použití, takže jej můžete zkompilovat kliknutím na
Změňte
Nyní prázdné okno oživíme. GTK uspořádává uživatelské rozhraní pomocí widgetů Gtk.Container
, které mohou obsahovat další widgety i další kontejnery. Zde použijeme nejjednodušší dostupný kontejner Gtk.Box
.
Přidejte následující řádky na začátek třídy Main
:
private Window window;
private Image image;
Nyní nahraďte současný konstruktor tímto uvedeným níže:
public Main () {
window = new Window ();
window.set_title ("Image Viewer in Vala");
// Nastaví uživatelské rozhraní
var box = new Box (Orientation.VERTICAL, 5);
var button = new Button.with_label ("Open image");
image = new Image ();
box.pack_start (image, true, true, 0);
box.pack_start (button, false, false, 0);
window.add (box);
// Zobrazí dialogové okno při otevírání souboru
button.clicked.connect (on_open_image);
window.show_all ();
window.destroy.connect (main_quit);
}
První dva řádky jsou částí GUI a budeme k nim potřebovat přístup z více než jedné metody. Proto je deklarujeme zde, takže budou přístupné skrze třídu. Jinak by byly přístupné jen v metodě, kde by byly vytvořeny.
První řádek konstruktoru vytvoří prázdné okno. Následující řádky vytvoří widgety, které chceme používat: tlačítko pro otevření obrázku, vlastní widget pro zobrazení obrázku a box sloužící jako kontejner.
Volání pack_start
přidává dva widgety do boxu a definuje jejich chování. Obrázek se roztáhne přes veškeré dostupné místo, zatímco tlačítko bude jen tak velké, jak je potřeba. Všimněte si, že jsem u widgetů výslovně nenastavili velikost. GTK to obvykle nepotřebuje, což usnadňuje udělat rozvržení, které vypadá dobře při různých velikostech okna. Následně je box přidán do okna.
Potřebujeme nadefinovat, co se stane, když uživatel klikne na tlačítko. GTK používá koncept signálů.
Když je kliknuto na button, vyšle se signál clicked
, který může být napojen na nějakou akci (definovanou v metodě zpětného volání).
To se udělá pomocí metody connect
signálu clicked
u tlačítka, což v tomto případě řekne GTK, aby ve chvíli, kdy je na tlačítko kliknuto, zavolalo (zatím nenadefinovanou) metodu zpětného volání on_image_open
. Zpětné volání nadefinujeme v další části.
Ve zpětném volání potřebujeme přístup k widgetům window
a image
, což je důvod, proč je definujeme jako soukromé členy na začátku naší třídy.
Poslední volání funkce connect
zajistí, že se aplikace ukončí, když je zavřeno okno. Kód, který vygenerovala Anjuta, volá metodu zpětného volání on_destroy
, která volá Gtk.main_quit
, ale prosté napojení signálu na main_quit
je jednodušší. Metodu on_destroy
můžete smazat.
Nyní nadefinujeme obsluhu signálu pro signál clicked tzn. pro tlačítko zmíněné dříve. Přidejte tento kód za konstruktor:
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 ();
}
Toto je trochu složitější, takže si to pojďme rozebrat:
Obsluha signálu je typ metody zpětného volání, která je volána, když je vyslán signál. Běžně se k označní používají oba termíny.
Prvním argumentem metody zpětného volání je vždy widget, který signál vyslal. Někdy za ním může následovat další argument související se signálem, ale clicked žádný nemá.
V tomto případě button
vyšle signál clicked
, který je napojen na metodu zpětného volání on_open_image
:
button.clicked.connect (on_open_image);
Metoda on_open_image
přebírá jako argument tlačítko, které vyslalo signál:
public void on_open_image (Button self)
Dalším zajímavým řádkem je ten, kde je vytvořeno dialogové okno pro výběr souboru. Konstruktor widgetu FileChooserDialog
přebírá název do záhlaví dialogového okna, rodičovské okno a několik voleb, jako je počet tlačítek a jim odpovídající hodnoty.
Všimněte si, že používáme standardní názvy tlačítek z Gtk, místo abychom ručně psali „Cancel“ nebo „Open“. Výhodou použití standardních názvů je, že popisky tlačítek budou vždy přeloženy do uživatelova jazyka.
Následující dva řádky omezí dialogové okno GtkImage
. Nejprve je vytvořen filtr a pak do něj přidáme všechny druhy souborů podporované v GdkPixbuf
(což zahrnuje většinu obrázkových formátů, včetně PNG a JPEG). Nakonec tento filtr nastavíme aby byl filtrem dialogového okna
dialog.run
zobrazí dialogové okno dialog.run
hodnotu typu ResponseType nebo by mohl vrátit , když uživatel klikne na switch
.
Při předpokladu, že uživatel klikl na GtkImage
, aby jej načetl a zobrazil.
Na posledním řádku této metody zlikvidujeme dialogové okno
Zlikvidováním se dialogové okno automaticky skryje.
Celý kód by nyní měl být připravený k fungování. Klikněte na
Pokud jste tak ještě neučinili, zvolte aplikaci
Pokud v této lekci narazíte na nějaké problémy, porovnejte si svůj kód s tímto ukázkovým kódem.
Zde je pár nápadů, jak byste mohli tuto jednoduchou ukázku rozšířit:
Nastavit ji tak, že když se okno otevře, bude mít konkrétní počáteční velikost. Například 200 × 200 pixelů.
Umožnit uživateli výběr složky místo souboru a poskytnout ovládání pro procházení všech obrázků v této složce.
Použít při načtení obrázku náhodné filtry a efekty a umožnit uživateli takto změněný obrázek uložit.
GEGL poskytuje mocné schopnosti pro práci s obrázky.
Umožnit uživateli načíst obrázky ze síťového sdílení, skenerů a dalších složitějších zdrojů.
Pro práci se síťovými přenosy můžete použít GIO a pro obsluhu skeneru GNOME Scan.