En este tutorial se va a crear un programa que abre un archivo de imagen y lo muestra. Aprenderá a:
Cómo configurar un proyecto básico usando el EID Anjuta.
Cómo escribir una aplicación de GTK+ en Vala
Algunos conceptos básicos de programación en GObject
Necesitará lo siguiente para poder seguir este tutorial:
Conocimiento básico del lenguaje de programación Vala.
Una copia instalada de
Puede que la referencia de la API de gtk+-3.0 le resulte útil, aunque no es necesaria para seguir el tutorial.
Antes de empezar a programar, deberá configurar un proyecto nuevo en Anjuta. Esto creará todos los archivos que necesite para construir y ejecutar el código más adelante. También es útil para mantener todo ordenado.
Inicie
En la pestaña
Asegúrese de que
Aprenderá a usar el constructor de interfaces en el tutorial del afinador de guitarra.
Pulse
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;
}
}
El código carga una ventana (vacía) desde el archivo de descripción de interfaz de usuario y la muestra. Se ofrecen más detalles a continuación; omita esta lista si entiende los conceptos básicos:
Las dos líneas using
importan espacios de nombres, por lo que no hay que nombrarlas explícitamente.
El constructor de la clase Main
crea una ventana (vacía) nueva y conecta una señal para salir de la aplicación cuando se cierra esa ventana.
Conectar señales es como se define lo que pasa cuando pulsa un botón, o cuando ocurre algún otro evento. Aquí, se llama a la función destroy
(y se sale de la aplicación) cuando cierra la ventana.
La función static main
se ejecuta de manera predeterminada cuando inicia una aplicación en Vala. Llama a algunas funciones que crean la clase Main
y configuran y ejecutan la aplicación. La función Gtk.main
inicia el bucle principal de GTK+, que ejecuta la interfaz de usuario y empieza a escuchar eventos (como pulsaciones del ratón y del teclado).
Este código está listo para usarse, por lo que puede compilarlo pulsando
Cambie la
Ahora se dará vida a la ventana vacía. GTK+ organiza la interfaz de usuario con varios Gtk.Container
que pueden contener otros widgets e incluso otros contenedores. Aquí se usará el contenedor más sencillo disponible, una Gtk.Box
.
Añada las siguientes líneas a la parte superior de la clase Main
:
private Window window;
private Image image;
Ahora reemplace el constructor actual con el siguiente:
public Main () {
window = new Window ();
window.set_title ("Image Viewer in Vala");
// Set up the UI
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);
// Show open dialog when opening a file
button.clicked.connect (on_open_image);
window.show_all ();
window.destroy.connect (main_quit);
}
Las dos primeras líneas son partes de la IGU a las que se debe acceder desde más de un método. Se declaran aquí, por lo que son accesibles mediante la clase en vez de serlo solamente en el método en el que se crearon.
Las primeras líneas del constructor crean la ventana vacía. Las siguientes líneas crean los widgets que se quieren usar: un botón para abrir una imagen, el widget de la vista de la imagen en sí y la caja que se usará como contenedor.
Las llamadas a pack_start
añaden los dos widgets a la caja y definen su comportamiento. La imagen se expandirá en cualquier espacio disponible, mientras que el botón será tan grande como se necesite. Se dará cuenta de que no se establecen tamaños explícitos de los widgets. Generalmente, en GTK+ no se necesita ya que hace que sea mucho más sencillo tener una distribución que se ve bien con diferentes tamaños de la ventana. A continuación, se añade la caja a la ventana.
Se debe definir qué pasa cuando el usuario pulsa en el botón. GTK+ usa el concepto de señales.
Cuando se pulsa el botón se emite la señal clicked
, que se puede conectar a alguna acción (definida en un método de un retorno de la llamada).
Esto se hace usando el método connect
de la señal clicked
de los botones, que en este caso indica a GTK+ que llame al método del retorno de la llamada on_image_open
(todavía no definida) cuando se pulsa el botón. El retorno de la llamada se definirá en la siguiente sección.
En el retorno de la llamada, se debe acceder a los widgets window
y image
que es por lo que se definen como miembros privados en la parte superior de la clase.
La última llamada a connect
asegura que la aplicación termina cuando se cierra la ventana. El código generado por Anjuta llamaba a un método on_destroy
que llamaba a Gtk.main_quit
, pero simplemente conectando la señal main_quit
directamente es más fácil. Puede eliminar el método on_destroy
.
Ahora se definirá el manejador de la señal clicked para el botón mencionado anteriormente. Añada este código después del constructor.
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 ();
}
Esto es un poco más complicado, así que se puede desglosar:
Un manejador de señal es un tipo de método de retorno de la llamada al que se llama cuando se emite la señal. Aquí se usan los términos intercambiados.
El primer argumento del método del retorno de la llamada es siempre el widget que envía la señal. A veces hay otros argumentos relativos a la señal que vienen después, pero clicked no tiene ninguno.
En este caso, el button
envía la señal clicked
, que se conecta al método del retorno de la llamada on_open_image
:
button.clicked.connect (on_open_image);
El método on_open_image
toma como argumento el botón que ha emitido la señal:
public void on_open_image (Button self)
La siguiente línea interesante es en la que se crea el diálogo para elegir el archivo. El constructor de FileChooserDialog
toma el título del diálogo, la ventana padre del diálogo y varias opciones como el número de botones y sus valores correspondientes.
Tenga en cuenta que se está usando nombres de botones del almacén de GTK+, en lugar de escribir manualmente «Cancelar» o «Abrir». La ventaja de usar nombres del almacén es que las etiquetas de los botones ya estarán traducidas en el idioma del usuario.
Las dos líneas siguientes restringen el diálogo GtkImage
. GtkImage es un widget que muestra una imagen. Primero se crea un objeto; luego se añaden los tipos de archivos soportados por el Gdk.Pixbuf
(que incluye la mayoría de los formatos de imagen como PNG y JPEG) al filtro. Por último, se establece que este filtro sea el filtro del diálogo
dialog.run
muestra el diálogo dialog.run
devolverá el valor ResponseType.ACCEPT
de ResponseType (devolvería ResponseType.CANCEL
si el usuario pulsara switch
comprueba esto.
Asumiendo que el usuario pulsó GtkImage
que cargue y muestre la imagen elegida.
En la última línea de este método se destruye el diálogo
Al destruir se oculta el diálogo automáticamente.
Todo el código debería estar listo para ejecutarse. Pulse
Si todavía no lo ha hecho, elija la aplicación
Si tiene problemas con este tutorial, compare su código con este código de referencia.
Aquí hay algunas ideas sobre cómo puede extender esta sencilla demostración:
Configúrela de tal manera que la ventana se abra con un tamaño determinado. Por ejemplo, 200x200 píxeles.
Haga que el usuario selecciona una carpeta en vez de un archivo, y proporcione controles para moverse por todas las imágenes de una carpeta.
Aplicar filtros aleatorios y efectos a la imagen cuando se carga y permitir al usuario guardar la imagen modificada.
GEGL proporciona la capacidad de manipular imágenes de manera potente.
Permitir al usuario cargar imágenes desde recursos de red compartidos, escáneres y otras fuentes más complicadas.
Puede usar GIO para gestionar transferencias de archivos de red y similares, y GNOME Scan para gestionar el escaneado.