A SpinButton is not related to a Spinner. It's a text entry field which only accepts numbers, and which has plus and minus buttons to let you change the value without having to type anything in.
It's best used when it's obvious that only a number can be entered into it. In this example, two SpinButtons are used for the number of kittens and number of cans of tuna to give them.
These are the libraries we need to import for this application to run. Remember that the line which tells GNOME that we're using Gjs always needs to go at the start.
All the code for this sample goes in the SpinButtonExample class. The above code creates a Gtk.Application for our widgets and window to go in.
The _buildUI function is where we put all the code to create the application's user interface. The first step is creating a new Gtk.ApplicationWindow to put all our widgets into.
We create each Label individually, and then string them together along with the SpinButtons. The last label needs to show the number of cans of tuna per kitten, so it has a variable in the middle, which corresponds to an equation that uses the SpinButtons' get_value functions to find out what they're set at. JavaScript's Math function's floor method is used to round the number of cans of tuna per kitten down to the nearest whole number.
Here we use Grid widgets to keep everything organized. One Grid holds the labels and SpinButtons in order, while the next puts that Grid on top and the final Label on the bottom.
There isn't a wrong way to organize things in Grids, so long as you like how it turns out. In this case, the top Grid has a margin on the bottom to keep it evenly spaced from the bottom Label, and the bottom Label is inside a separate Grid so it will be centered relative to the Labels and SpinButtons on the top.
Finally, we add the larger Grid to the window, then tell the window to show itself and all the widgets inside of it.
#!/usr/bin/gjs
imports.gi.versions.Gtk = '3.0';
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
class SpinButtonExample {
// Create the application itself
constructor() {
this.application = new Gtk.Application({
application_id: 'org.example.jsspinbutton'
});
// Connect 'activate' and 'startup' signals to the callback functions
this.application.connect('activate', this._onActivate.bind(this));
this.application.connect('startup', this._onStartup.bind(this));
}
// Callback function for 'activate' signal presents window when active
_onActivate() {
this._window.present();
}
// Callback function for 'startup' signal builds the UI
_onStartup() {
this._buildUI();
}
// Build the application's UI
_buildUI() {
// Create the application window
this._window = new Gtk.ApplicationWindow({
application: this.application,
window_position: Gtk.WindowPosition.CENTER,
border_width: 20,
title: "Kitten Feeder"});
// Create the first spinbutton using a function
this._kittens = Gtk.SpinButton.new_with_range (1, 9001, 1);
this._kittens.connect ("value-changed", this._newValue.bind(this));
// Create an adjustment to use for the second spinbutton
this._adjustment = new Gtk.Adjustment ({
value: 1,
lower: 0,
upper: 9001,
step_increment: 1,
page_increment: 10 });
// Create the second spinbutton
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);
// Create the text labels to go with the spinbuttons
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." });
// Create a grid to put the spinbuttons and their labels in
this._spinGrid = new Gtk.Grid ({
halign: Gtk.Align.CENTER,
valign: Gtk.Align.CENTER,
margin_bottom: 20 });
// Attach everything to the grid
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);
// Create a main grid to hold it and the last label
this._mainGrid = new Gtk.Grid ({
halign: Gtk.Align.CENTER,
valign: Gtk.Align.CENTER });
// Attach the smaller grid and the last label to the main grid
this._mainGrid.attach (this._spinGrid, 0, 0, 1, 1);
this._mainGrid.attach (this._lastLabel, 0, 1, 1, 1);
// Add the main grid to the window
this._window.add (this._mainGrid);
// Show the window and all child widgets
this._window.show_all();
}
_newValue() {
// Update the label which shows how many cans there are per kitten
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.");
}
};
// Run the application
let app = new SpinButtonExample ();
app.application.run (ARGV);
Gtk.Adjustment
Gtk.Application
Gtk.ApplicationWindow
Gtk.Grid
Gtk.Label
Gtk.SpinButton