Este es uno de los capítulos del tutorial Aplicaciones nativas en JavaScript con GJS. Encontrarás los enlaces a todos los de capítulos, al final de este artículo.
Hasta el momento, en los diferentes capítulos del tutorial, básicamente el usuario de tu aplicación, poco podía hacer. En el capítulo anterior, viste como mostrar un texto a tu usuario para que pudiera leerlo, pero, sinceramente, tu quieres que el usuario interactúe con tu aplicación, que se relacione. Una forma, sencilla, de interacción es mediante el uso de botones. Pulsando un botón u otro botón, puedes conseguir esa interacción que buscas. Así, en este capítulo verás como implementar botones con JavaScript.
Ciertamente, en capítulos anteriores del tutorial ya lo hacías, a través de los propios botones de las ventanas que has utilizado para mostrar otros widgets. En este capítulo, tienes la oportunidad de exprimir los botones al máximo.
Botones en JavaScript
La clase Gtk.Button
es la clase base de la que derivan otros tipos de botones en JavaScript. Por supuesto, tu también la puedes utilizar como la clase base para tus propios botones. Este tipo de botones, pueden contener tanto texto como imágenes.
El ejemplo
Para ver todas las propiedades de un objeto de la clase Gtk.Button
, utilizaré el siguiente ejemplo. En ejemplos posteriores, tendrás que sustituir la definición del Gtk.Button
.
#!/usr/bin/env gjs
imports.gi.versions.Gtk = '3.0'
const {Gtk, GObject} = imports.gi;
Gtk.init(null);
var Ventana = GObject.registerClass(
class Ventana extends Gtk.Window{
_init(){
super._init({
defaultWidth:200,
defaultHeight: 200
});
this.connect('destroy', ()=>{
Gtk.main_quit();
});
let layout = new Gtk.Grid({
margin: 10
});
this.add(layout);
let button = new Gtk.Button({
label: 'Di_alogo',
alwaysShowImage: true,
focusOnClick: true,
image: new Gtk.Image({iconName: 'starred'}),
imagePosition: Gtk.PositionType.BOTTOM,
relief: Gtk.ReliefStyle.NORMAL,
useUnderline: true
});
button.connect('clicked', () => {
let dialog = new Gtk.MessageDialog({
title: 'Ejemplo',
text: 'Ejemplo de diálogo'
});
dialog.add_button('Si', Gtk.ResponseType.YES);
dialog.run();
dialog.destroy();
});
layout.attach(button, 0, 0, 1, 1);
}
}
);
let ventana = new Ventana();
ventana.show_all();
Gtk.main();
Las propiedades de los botones en JavaScript
Quiero destacar un pequeño detalle, y es como están declaradas las propiedades. En la documentación encontrarás image_position
, sin embargo, en el caso de JavaScript, puedes utilizar de forma indistinta tanto esta forma, como imagePosition
. Si bien, la convención es utilizar esta segunda manera. Es decir, utilizar CamelCase, que consiste en utilizar mayúsculas al inicio de cada palabra en una palabra compuesta.
En el ejemplo anterior, he definido algunas de las propiedades intrínsecas de Gtk.Button
, y que te describo a continuación,
label: 'Di_alogo'
. Esto mostrará el textoDialogo
en el botón, siempre y cuando la propiedaduseUnderline
sea cierta. Mas adelante te comento que es esto delunderline
.alwaysShowImage: true
. Por defecto en los botones y otros objetos no se muestran imágenes, excepto que esta propiedad esté definida comotrue
porque su valor por defecto esfalse
.focusOnClick: true
. Con esta propiedad defines el comportamiento del botón ante un clic sobre el mismo. Por defecto esta propiedad tiene el valortrue
, y es que cuando haces clic sobre el botón el botón gana el foco. Si lo defines afalso
, cuando hagas clic el botón no ganará el foco, y permanecerá en el que lo tuviera en ese momento.image: new Gtk.Image({iconName: 'starred'})
. Esta propiedad te permite añadir una imagen en el botón. No te preocupes por este objetoGtk.Image
por que lo podrás ver con detenimiento en un capítulo del tutorial dedicado en exclusiva. Por supuesto, para que se muestre la imagen es necesario que la propiedad que has visto antes,alwaysShowImage
esté definida comotrue
.imagePosition: Gtk.PositionType.BOTTOM
. En el caso de que exista una imagen, esta propiedad define donde se mostrará la imagen en el botón. Esta propiedad toma los valoresBOTTOM
,LEFT
,RIGHT
yTOP
.relief: Gtk.ReliefStyle.NORMAL
. Esta propiedad se refiere a como se muestra el botón. Los valores que puede tomar la propiedad sonHALF
,NONE
yNORMAL
.useUnderline: true
. En este caso, esta propiedad te permite definir aceleradores. Los aceleradores son atajos de teclado que te permitirán realizar acciones sin necesidad de recurrir al ratón. Esta propiedad se utiliza en combinación con la propiedadlabel
, tal y como te he comentado antes. Para indicar cual es el atajo de teclado tienes que utilizar un guión bajo,_
delante de la letra que quieres que se convierta en acelerador. En el caso de este ejemploDi_alogo
. Si ahora, pulsas la teclaAlt
, verás que la letraa
aparece subrayada. Pulsandoa
sin dejar de pulsarAlt
verás que haces clic en el botón.
Estas son las propiedades mas interesantes de Gtk.Button
, pero además de las propiedades, este objeto está sometido a eventos que generan señales, que tu puedes utilizar para desencadenar acciones.
Las señales
Existen varias señales que puedes utilizar con un objeto de la clase Gtk.Button
, pero sin lugar a dudas la que mas importante de ellas es clicked
. Básicamente es la señal que se produce cuando se hace clic sobre el botón, como ya te podías imaginar. En el caso del ejemplo anterior, está conectada a una función que te mostrará un sencillo cuadro de diálogo,
button.connect('clicked', () => {
let dialog = new Gtk.MessageDialog({
title: 'Ejemplo',
text: 'Ejemplo de diálogo'
});
dialog.add_button('Si', Gtk.ResponseType.YES);
dialog.run();
dialog.destroy();
});
De la misma forma tienes estas otras señales, que puedes conectar de la misma forma que lo has hecho con la señal clicked
.
enter
. Esta señal se produce justo en el momento de entrar con el ratón en el área del botón. Así, por ejemplo, podrías hacer exactamente lo mismo que en el caso anterior, pero sin que el usuario de tu aplicación pulse el botón, simplemente con pasar con el ratón sobre el botón.leave
. Justo la señal opuesta a la anterior. Es decir, la señal se produce cuando sales del área del botón.
Existen otras señales como puede ser activate
, pressed
o released
, pero actualmente han quedado obsoletas y están deprecadas, por lo que te deberías ceñir a utilizar estas que he indicado.
Gtk.ToggleButton
La primera de las clases derivadas de la clase Gtk.Button
es Gtk.ToggleButton
. Esta clase tiene un comportamiento un tanto peculiar y diferente a un simple botón. Cuando haces clic sobre un botón este vuelve al estado natural, es como cuando pulsas el timbre de una casa. Sin embargo, un objeto de la clase Gtk.ToggleButton
se comporta mas como un interruptor, de forma que se quedará pulsado, y para que vuelva al estado original deberás de pulsar el botón.
Esto queda definido por la propiedad active
que te indicará el estado en que se encuentra esté botón. Es decir, que con la propiedad active
, sabrás si el botón se encuentra en estado pulsado, si es true
o no se encuentra pulsado, si es false
.
Además tiene una nueva señal, toggled
, que se produce cuando Gtk.ToggleButton
cambia de estado, pasando de activo a inactivo o al revés.
Puedes analizar el comportamiento de un objeto de la clase Gtk.ToggleButton
modificando algunas líneas del ejemplo anterior por las siguientes,
let button = new Gtk.ToggleButton({
label: 'Botton'
});
button.connect('toggled', () => {
log(button.get_active());
});
Gtk.LinkButton
Otro de los botones en JavaScript es Gtk.LinkButton. Esta otra clase derivada te permite colocar enlaces de forma sencilla dentro de tu aplicación. Así, introduce una nueva propiedad uri
que te permite indicar el enlace al que apunta, y donde te dirigirá en el caso de hacer clic sobre el botón.
Un ejemplo del funcionamiento,
let button = new Gtk.LinkButton({
label: 'Llévame a atareao.es',
uri: 'https://atareao.es'
});
button.connect('clicked', () => {
log('Has hecho clic');
});
Gtk.ColorButton
Este botón es ideal para permitir al usuario seleccionar un color. Inicialmente, al mostrar el botón se muestra el color que tu hayas predefinido, si es que lo has hecho. La gracia de este botón, es que no es necesario que implementes ninguna acción, porque esta ya está definida por defecto. Al hacer clic sobre este botón, se muestra un cuadro de diálogo que permite al usuario seleccionar el color.
Por ejemplo,
let button = new Gtk.ColorButton({
rgba: new Gdk.RGBA({
red: 0.0,
green: 1.0,
blue: 1.0,
alpha: 0.5
})
});
Este botón tienes varios métodos relacionados con el color que te permite definir u obtener el color seleccionado. Estos métodos son los siguientes,
set_color
get_color
set_alpha
get_alpha
set_rgba
get_rgba
get_use_alpha
set_use_alpha
Además este botón incorpora una nueva señal set-color
que te permite conocer cuando se ha modificado el color.
Gtk.FontButton
Este tipo de botón es muy similar en características al anterior, pero en lugar de permitirte elegir colores te permite elegir tipografías. Me refiero a que es similar al anterior, en el sentido de que no es necesario que implementes ninguna acción para el evento clicked
. Y es que al hacer clic, sobre el botón te mostrará un cuadro de diálogo donde puedes seleccionar una tipografía o modificar las características de la tipografía actual.
Este botón tiene algunas propiedades especiales que permiten definir la tipografía que quieres mostrar en el botón y como mostrarla. Por ejemplo,
let button = new Gtk.FontButton({
fontName: 'Ubuntu 12',
showSize: true,
showStyle: true,
title: 'Selecciona una fuente',
useFont: true,
useSize: true
});
fontName: 'Ubuntu 12'
define la fuente y el tamaño de la mismashowSize: true
establece si se muestra por defecto el tamaño en el botón, que por defecto es así.showStyle: true
igual que en el caso anterior pero para el estilo.title: 'Selecciona una fuente'
este es el título que se mostrará en el cuadro de diálogo que aparece al hacer clic sobre el botón.useFont: true
define si se utiliza la fuente en el propio botón.useSize: true
lo mismo que en el caso anterior pero para el tamaño de la fuente. Imagina que por defecto estableces la tipografía con un tamaño40
. No deberías utilizar este tamaño para el texto del botón.
También, al igual que en el caso anterior, tienes métodos para consultar la tipografía establecida o para establecerla.
Y de la misma forma, tienes la señal set-font
que te permite conocer cuando se ha modificado la tipografía. Por ejemplo,
button.connect('font-set', () => {
log('Has seleccionado una nueva tipografía');
});
Gtk.ScaleButton
Este botón te permite seleccionar un valor de una escala. Al pulsar el botón se despliega una escala. Por ejemplo,
let button = new Gtk.ScaleButton({
icons: ['battery-empty', 'battery-full'],
adjustment: new Gtk.Adjustment({
lower: 0,
upper: 99,
pageSize: 10,
pageIncrement: 5,
stepIncrement: 1,
value: 50
})
});
Aunque Gtk.ScaleButton
tiene algunas propiedades mas, me quedo con estas dos que son las mas relevantes para el uso de este botón.
icons
esta propiedad define los iconos que se mostrarán en función del valor que tenga el botón. En el ejemplo anterior, si el valor es inferior a 50 mostrará un icono de una batería vacía, mientras que si es superior mostrará un icono de una batería llena.Es posible definir mas iconos, pero siempre el primero se corresponde con el menor valor, mientras que el segundo con el mayor valor. El resto, se repartirá.
Por otro lado, este objeto tiene tres señales,
popdown
esta señal se produce cuando desaparece la escala.popup
, la señal opuesta a la anterior, es decir, se produce cuando aparece la escala.value-changed
, esta señal se produce cuando cambia el valor.
Conclusiones
Existen algunos botones en JavaScript mas de los que te he mostrado aquí, pero el comportamiento es similar a estos, y son mucho mas específicos.
De la misma forma, aquí no te he expuesto todas y cada una de las propiedades, métodos y señales de estos objetos, pero si, los que he considerado mas relevantes.
Más información,