<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" xmlns:xi="http://www.w3.org/2001/XInclude" type="guide" style="task" id="spinbutton.js" xml:lang="cs">
<info>
<title type="text">SpinButton (JavaScript)</title>
<link type="guide" xref="beginner.js#entry"/>
<link type="seealso" xref="GtkApplicationWindow.js"/>
<link type="seealso" xref="grid.js"/>
<link type="seealso" xref="label.js"/>
<revision version="0.1" date="2012-06-24" status="draft"/>
<credit type="author copyright">
<name>Taryn Fox</name>
<email its:translate="no">jewelfox@fursona.net</email>
<years>2012</years>
</credit>
<desc>Číselné vstupní pole, které má tlačítka + a -</desc>
</info>
<title>SpinButton</title>
<media type="image" mime="image/png" src="media/spinbuttonkittens.png"/>
<p>SpinButton (číselník) nemá žádnou souvislost s widgetem <link xref="spinner.js">Spinner</link> (káča). Jedná se o textové vstupní pole, které přijímá jen čísla a má tlačítka plus a mínus, která umožňují měnit hodnout, aniž byste museli psát.</p>
<p>Je nejlepší pro použití v situacích, kdy je potřeba zadávat čistě číselné hodnoty. V tomto příkladu jsou dva číselníky použity pro počet koček a počet tuňákových konzerv pro ně.</p>
<links type="section"/>
<section id="imports">
<title>Importované knihovny</title>
<code mime="application/javascript">
#!/usr/bin/gjs
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
</code>
<p>Toto jsou knihovny, které potřebujeme naimportovat, aby aplikace běžela. Pamatujte si, že řádek, který GNOME říká, že používáme Gjs, musí být vždy na začátku.</p>
</section>
<section id="applicationwindow">
<title>Vytvoření okna aplikace</title>
<code mime="application/javascript">
const SpinButtonExample = new Lang.Class({
Name: 'SpinButton Example',
// Vytvoří vlastní aplikaci
_init: function() {
this.application = new Gtk.Application({
application_id: 'org.example.jsspinbutton'
});
// Připojí signály "activate" a "startup" k funkcím zpětného volání
this.application.connect('activate', Lang.bind(this, this._onActivate));
this.application.connect('startup', Lang.bind(this, this._onStartup));
},
// Funkce zpětného volání pro signál "activate" zobrazujicí okno při aktivaci
_onActivate: function() {
this._window.present();
},
// Funkce zpětného volání pro signál "startup" sestavující uživatelské rozhraní
_onStartup: function() {
this._buildUI ();
},
</code>
<p>Všechen kód této ukázky je ve třídě <code>SpinButtonExample</code>. Výše uvedený kód vytvoří <link href="http://www.roojs.com/seed/gir-1.2-gtk-3.0/gjs/Gtk.Application.html">Gtk.Application</link> pro naše widgety a okno, ve kterém budou.</p>
<code mime="application/javascript">
// Sestaví uživatelské rozhraní aplikace
_buildUI: function() {
// Vytvoří okno aplikace
this._window = new Gtk.ApplicationWindow({
application: this.application,
window_position: Gtk.WindowPosition.CENTER,
border_width: 20,
title: "Kitten Feeder"});
</code>
<p>Funkce <code>_buildUI</code> je místo, ze kterého voláme všechen kód, který vytváří uživatelské rozhraní aplikace. Prvním krokem je vytvoření nového <link xref="GtkApplicationWindow.js">Gtk.ApplicationWindow</link>, do kterého vložíme všechny naše widgety.</p>
</section>
<section id="spinbutton">
<title>Vytvoření widgetů SpinButton</title>
<code mime="application/javascript">
// Pomocí funkce vytvoří první číselník
this._kittens = Gtk.SpinButton.new_with_range (1, 9001, 1);
this._kittens.connect ("value-changed", Lang.bind (this, this._newValue));
</code>
<p>K rychlému vytvoření číselníku můžeme použít funkci <code>new_with_range</code>. Prvním parametrem je počáteční hodnota číselníku, druhým maximální hodnota a třetím velikost kroku použitého při mačkání tlačítek plus nebo mínus.</p>
<p>Po vytvoření prvního číselníku napojíme jeho signál "value-changed" k funkci, která zpracovává, co se má stát, když se číslo uvnitř číselníku změní.</p>
<code mime="application/javascript">
// Vytvoří přizpůsobení, které se použije pro druhý číselník
this._adjustment = new Gtk.Adjustment ({
value: 1,
lower: 0,
upper: 9001,
step_increment: 1,
page_increment: 10 });
// Vytvoří druhý číselník
this._tuna = new Gtk.SpinButton ({ adjustment: this._adjustment });
this._tuna.connect ("value-changed", Lang.bind (this, this._newValue));
// this._tuna.set_digits (1);
// this._tuna.set_wrap (true);
</code>
<p>Jestli chcete jemnější kontrolu nad widgetem <code>SpinButton</code> nebo chcete vytvořit spoustu číselníků, které budou mít stejné parametry, můžete vytvořit objekt <link href="http://www.roojs.org/seed/gir-1.2-gtk-3.0/gjs/Gtk.Adjustment.html">Adjustmen</link> (přizpůsobení). Pak můžete použít tento objekt jako vlastnost <code>adjustment</code> pro nový číselník a tím ji nastavit všechny vlastnosti naráz. Později můžete změnit všechny číselníky, které používají toto přizpůsobení naráz pouhou změnou některé vlastnosti objektu <code>Adjustment</code>.</p>
<p>Řádky zde zakomentované ukazují věci, které si můžete u číselníků přizpůsobit. Můžete například nastavit počet číslic za desetinnou čárkou nebo říci, aby se při dosažení nastavené horní nebo dolní meze cyklicky přešlo na opačný konec.</p>
<note><p>V zájmu zdraví koček nepoužívejte prosím metodu <code>set_digits</code>, která by umožnila necelé počty koček.</p></note>
</section>
<section id="UI">
<title>Vytvoření zbytku uživatelského rozhraní</title>
<code mime="application/javascript">
// Vytvoří textové popisky, které budou u číselníků
this._startLabel = new Gtk.Label ({ label: "There are " });
this._kittenLabel = new Gtk.Label ({ label: " kitten(s), and "});
this._tunaLabel = new Gtk.Label ({ label: " can(s) of tuna."});
this.perKitten = Math.floor((this._tuna.get_value() / this._kittens.get_value()));
this._lastLabel = new Gtk.Label ({
label: "That's " + this.perKitten + " can(s) of tuna per kitten." });
</code>
<p>Každý widget <link xref="label.js">Label</link> vytvoříme samostatně a pak je spojíme dohromady s jednotlivými číselníky. Poslední popisek potřebujeme na zobrazování počtu konzerv tuňáka na kočku, takže má uprostřed proměnnou odpovídající výpočtu, který používá funkce <code>get_value</code> u číselníků k zjištění, co je v nich nastaveno. Funkce <code>floor</code> z objektu <code>Math</code> jazyka JavaScript se použije k zaokrouhlení počtu konzerv tuňáka na kočku na nejbližší nižší celé číslo.</p>
<code mime="application/javascript">
// Vytvoří mřížku pro vložení číselníků a jejich popisků
this._spinGrid = new Gtk.Grid ({
halign: Gtk.Align.CENTER,
valign: Gtk.Align.CENTER,
margin_bottom: 20 });
// Připojí vše do mřížky
this._spinGrid.attach (this._startLabel, 0, 0, 1, 1);
this._spinGrid.attach (this._kittens, 1, 0, 1, 1);
this._spinGrid.attach (this._kittenLabel, 2, 0, 1, 1);
this._spinGrid.attach (this._tuna, 3, 0, 1, 1);
this._spinGrid.attach (this._tunaLabel, 4, 0, 1, 1);
// Vytvoří hlavní mřížku, která bude obsahovat tu předchozí a poslední popisek
this._mainGrid = new Gtk.Grid ({
halign: Gtk.Align.CENTER,
valign: Gtk.Align.CENTER });
// Připojí menší mřížku a posledního popisek do hlavní mřížky
this._mainGrid.attach (this._spinGrid, 0, 0, 1, 1);
this._mainGrid.attach (this._lastLabel, 0, 1, 1, 1);
</code>
<p>Zde používáme widgety <link xref="grid.js">Grid</link>, které vše udržují správně rozložené. Jedna mřížka obsahuje ve správném pořadí popisky a číselníky, zatímco následující obsahuje na hoře ji a dole konečný popisek.</p>
<p>Rozhodně není špatný způsob, hrát si s uspořádáním věcí do mřížek tak dlouho, až získáte to, co si přejete. V tomto případě má horní mřížka dole okraj, aby se uchoval odstup od spodního popisku a spodní popisek je uvnitř další mřížky, aby byl vystředěn relativně vůči popiskům a číselníkům nahoře.</p>
<code mime="application/javascript">
// Přidá mřížku do okna
this._window.add (this._mainGrid);
// Zobrazí okno a všechny jeho synovské widgety
this._window.show_all();
},
</code>
<p>Nakonec přidáme větší mřížku do okna a oknu řekneme, že má zobrazit sebe a všechny widgety uvnitř sebe.</p>
</section>
<section id="spinbutton-handler">
<title>Funkce, která obsluhuje změny číselných hodnot widgetů SpinButton</title>
<code mime="application/javascript">
_newValue: function () {
// Aktualizuje popisek, který zobrazuje, kolik konzerv připadá na jednu kočku
this.perKitten = Math.floor((this._tuna.get_value() / this._kittens.get_value()))
this._lastLabel.set_label ("That's " + this.perKitten + " can(s) of tuna per kitten.");
}
});
</code>
<p>Zde aktualizujeme proměnnou <var>perKitten</var> vycházející z nových hodnot v číselnících a použijeme vlastnost <code>set_label</code> k občerstvení údaje, který zobrazuje <code>_lastLabel</code>. Protože mají oba číselníky své signály <code>"value-changed"</code> napojené na tuto funkci, aktualizuje tato funkce popisek pokaždé, když se změní některá z hodnot.</p>
<code mime="application/javascript">
// Spustí aplikaci
let app = new SpinButtonExample ();
app.application.run (ARGV);
</code>
<p>Nakonec vytvoříme novou instanci konečné třídy SpinButtonExample a aplikaci spustíme.</p>
</section>
<section id="complete">
<title>Úplný kód ukázky</title>
<code mime="application/javascript" style="numbered">#!/usr/bin/gjs
imports.gi.versions.Gtk = '3.0';
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
class SpinButtonExample {
// Vytvoří vlastní aplikaci
constructor() {
this.application = new Gtk.Application({
application_id: 'org.example.jsspinbutton'
});
// Napojí signály "activate" a "startup" k funkcím zpětného volání
this.application.connect('activate', this._onActivate.bind(this));
this.application.connect('startup', this._onStartup.bind(this));
}
// Funkce zpětného volání pro signál "activate" zobrazujicí okno při aktivaci
this.application.connect('activate', this._onActivate.bind(this));
this.application.connect('startup', this._onStartup.bind(this));
}
// Funkce zpětného volání pro signál "startup" sestavující uživatelské rozhraní
_onStartup() {
this._buildUI();
}
// Sestaví uživatelské rozhraní aplikace
_buildUI() {
// Vytvoří okno aplikace
this._window = new Gtk.ApplicationWindow({
application: this.application,
window_position: Gtk.WindowPosition.CENTER,
border_width: 20,
title: "Kitten Feeder"});
// Vytvoří pomocí funkce první číselník
this._kittens = Gtk.SpinButton.new_with_range (1, 9001, 1);
this._kittens.connect ("value-changed", this._newValue.bind(this));
// Vytvoří přizpůsobení, které se použije pro druhý číselník
this._adjustment = new Gtk.Adjustment ({
value: 1,
lower: 0,
upper: 9001,
step_increment: 1,
page_increment: 10 });
// Vytvoří druhý číselník
this._tuna = new Gtk.SpinButton ({ adjustment: this._adjustment });
this._tuna.connect ("value-changed", this._newValue.bind(this));
// this._tuna.set_digits (1);
// this._tuna.set_wrap (true);
// Vytvoří textový popisek, který bude u číselníku
this._startLabel = new Gtk.Label ({ label: "There are " });
this._kittenLabel = new Gtk.Label ({ label: " kitten(s), and "});
this._tunaLabel = new Gtk.Label ({ label: " can(s) of tuna."});
this.perKitten = Math.floor((this._tuna.get_value() / this._kittens.get_value()));
this._lastLabel = new Gtk.Label ({
label: "That's " + this.perKitten + " can(s) of tuna per kitten." });
// Vytvoří mřížku, do které se vloží číselníky a jejich popisky
this._spinGrid = new Gtk.Grid ({
halign: Gtk.Align.CENTER,
valign: Gtk.Align.CENTER,
margin_bottom: 20 });
// Připojí vše do mřížky
this._spinGrid.attach (this._startLabel, 0, 0, 1, 1);
this._spinGrid.attach (this._kittens, 1, 0, 1, 1);
this._spinGrid.attach (this._kittenLabel, 2, 0, 1, 1);
this._spinGrid.attach (this._tuna, 3, 0, 1, 1);
this._spinGrid.attach (this._tunaLabel, 4, 0, 1, 1);
// Vytvoří hlavní mřížku, která bude obsahovat poddružnou mřížku a poslední popisek
this._mainGrid = new Gtk.Grid ({
halign: Gtk.Align.CENTER,
valign: Gtk.Align.CENTER });
// Připojí poddružnou mříku a poslední popisek do hlavní mřížky
this._mainGrid.attach (this._spinGrid, 0, 0, 1, 1);
this._mainGrid.attach (this._lastLabel, 0, 1, 1, 1);
// Přidá hlavní mřížku do okna
this._window.add (this._mainGrid);
// Zobrazí okno a všechny jeho synovské widgety
this._window.show_all();
}
_newValue() {
// Aktualizuje popisek, který zobrazuje kolik konzerv připadá na jednu kočku
this.perKitten = Math.floor((this._tuna.get_value() / this._kittens.get_value()))
this._lastLabel.set_label ("That's " + this.perKitten + " can(s) of tuna per kitten.");
}
};
// Spustí aplikaci
let app = new SpinButtonExample ();
app.application.run (ARGV);
</code>
</section>
<section id="in-depth">
<title>Dokumentace jdoucí do hloubky</title>
<list>
<item><p><link href="http://www.roojs.org/seed/gir-1.2-gtk-3.0/gjs/Gtk.Adjustment.html">Gtk.Adjustment</link></p></item>
<item><p><link href="http://www.roojs.com/seed/gir-1.2-gtk-3.0/gjs/Gtk.Application.html">Gtk.Application</link></p></item>
<item><p><link href="http://developer.gnome.org/gtk3/stable/GtkApplicationWindow.html">Gtk.ApplicationWindow</link></p></item>
<item><p><link href="http://www.roojs.org/seed/gir-1.2-gtk-3.0/gjs/Gtk.Grid.html">Gtk.Grid</link></p></item>
<item><p><link href="http://www.roojs.org/seed/gir-1.2-gtk-3.0/gjs/Gtk.Label.html">Gtk.Label</link></p></item>
<item><p><link href="http://www.roojs.org/seed/gir-1.2-gtk-3.0/gjs/Gtk.SpinButton.html">Gtk.SpinButton</link></p></item>
</list>
</section>
</page>