# SpinButton (JavaScript)

Taryn Fox
jewelfox@fursona.net 2012
Číselné vstupní pole, které má tlačítka + a -

# SpinButton

SpinButton (číselník) nemá žádnou souvislost s widgetem Spinner (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.

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ě.

# Importované knihovny

#!/usr/bin/gjs

const Gio = imports.gi.Gio; const Gtk = imports.gi.Gtk; const Lang = imports.lang;

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.

# Vytvoření okna aplikace

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 (); },

Všechen kód této ukázky je ve třídě `SpinButtonExample`. Výše uvedený kód vytvoří Gtk.Application pro naše widgety a okno, ve kterém budou.

// 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"});

Funkce `_buildUI` 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 Gtk.ApplicationWindow, do kterého vložíme všechny naše widgety.

# Vytvoření widgetů SpinButton

// 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));

K rychlému vytvoření číselníku můžeme použít funkci `new_with_range`. 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.

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í.

// 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);

Jestli chcete jemnější kontrolu nad widgetem `SpinButton` nebo chcete vytvořit spoustu číselníků, které budou mít stejné parametry, můžete vytvořit objekt Adjustmen (přizpůsobení). Pak můžete použít tento objekt jako vlastnost `adjustment` 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 `Adjustment`.

Řá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.

V zájmu zdraví koček nepoužívejte prosím metodu `set_digits`, která by umožnila necelé počty koček.

# Vytvoření zbytku uživatelského rozhraní

// 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." });

Každý widget Label 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 `get_value` u číselníků k zjištění, co je v nich nastaveno. Funkce `floor` z objektu `Math` jazyka JavaScript se použije k zaokrouhlení počtu konzerv tuňáka na kočku na nejbližší nižší celé číslo.

// 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);

Zde používáme widgety Grid, 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.

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řidá mřížku do okna this._window.add (this._mainGrid);

// Zobrazí okno a všechny jeho synovské widgety this._window.show_all(); },

Nakonec přidáme větší mřížku do okna a oknu řekneme, že má zobrazit sebe a všechny widgety uvnitř sebe.

# Funkce, která obsluhuje změny číselných hodnot widgetů SpinButton

_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.");

}

});

Zde aktualizujeme proměnnou perKitten vycházející z nových hodnot v číselnících a použijeme vlastnost `set_label` k občerstvení údaje, který zobrazuje `_lastLabel`. Protože mají oba číselníky své signály `"value-changed"` napojené na tuto funkci, aktualizuje tato funkce popisek pokaždé, když se změní některá z hodnot.

// Spustí aplikaci let app = new SpinButtonExample (); app.application.run (ARGV);

Nakonec vytvoříme novou instanci konečné třídy SpinButtonExample a aplikaci spustíme.

# Úplný kód ukázky

#!/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);

# Dokumentace jdoucí do hloubky

Gtk.Adjustment

Gtk.Application

Gtk.ApplicationWindow

Gtk.Grid

Gtk.Label

Gtk.SpinButton