Hoy expondré cómo hacer un programa para visualizar imágnes.
La dinámica es muy sencilla, el usuario en un textbox escribirá la dirección de la imágen que se desea visualizar y la aplicación buscará la imágen y la desplegará.
En el post anterior habia explicado como se podía hacer un pequeño hola_mundo.c para nuestro celular nokia n900, usaremos este mismo principio para hacer esta aplicación.
Para hacer la parte gráfica usaremos GTK. Quien necesite más ayuda en entender que demónios es GTK, recomiendo esta lectura.
Lo primero que haremos es el programa en C. Antes de emepzar el código, sería importante explicar como se manejan los eventos con GTK. Cuando digo eventos, me refiero al hecho de que el usuario oprima un botón por ejemplo. Cuando sucede algo así, debemos tener alguna manera de poder detectar que eso sucedió, y de decir, hmm el usuario oprimió el botón de enviar, entonces quiero, por ejemplo, leer lo que el usuario escribió en el textbox, y procesar después esa información.
Con GTK para poder hacer esto, lo que debemos hacer es conectar las señales que envía el botón (señales de que ya fue oprimido) con alguna función que hará lo que deseamos que suceda cuando se oprima ese botón. La función g_signal_connect, logra esto.
La funcion recibe los siguientes parámetros:
g_signal_connect(Objeto_Que_Emite_Las_Señales,tipo_de_señal_a_detectar,funcion_que_procesará_la_info,variable_a_procesar_en_la_funcion).
En este caso, esa función, nos quedaría de la siguiente manera:
g_signal_connect (G_OBJECT(button), "clicked",G_CALLBACK (on_button_clicked),&valorcitos);
En donde on_button_clicked, es la función que procesará que se hará cuando se oprima el botón.Y valorcitos, es de hecho una estructura que guardará todos los valores que queremos modificar en la función cuando se oprima el botón. En este caso, se escojió una estructura, porque en sí, sólo se puede enviar una variable a la función de on_button_clicked. Pero en este caso, necesitamos minímo enviar dos: la variable de tipo imagen, y la variable de tipo textbox, pues necesitamos leer lo que el usuario escribió, y dependiendo de eso, desplegar la imagen adecuada.
Resumiendo...Nuestro código nos quedaría de la siguiente forma:(Disculpen que los comentarios esten en inglés,no sé que me está sucediendo que programo ya con comentarios en inglés..:-(
/*
Program that displays a desired image
specified by the user.
by:saiph*/
#include
#include stdio.h
/* Introduce types and prototypes of GTK+ for the compiler. */
#include gtk/gtk.h
/*This struct will store some of the variables that will be modified when the user clicks the button */
struct values
{
GtkWidget *image;
GtkWidget *entry;
GtkWidget *vbox;
GtkWidget *table;
GtkWidget *label;
};
/*The function that will say what will happen when the user clicks the button, user_data stores the variables that we need to retrive from the main
function to play around with.
*/
G_MODULE_EXPORT void on_button_clicked(GtkButton *object, gpointer user_data)
{
gchar * name_file; /*gchar will store the name of the image that we wish to display*/
struct values *valorcitos;
valorcitos=user_data;/*we obtain a struct that stores the needed variables.*/
// we read the name of the image that the //user wants to display
name_file=(gchar*)gtk_entry_get_text(GTK_ENTRY
(valorcitos->entry));
/* we check to see if the image exists.
If it does, we will display it!=)
If not, we will print a label that says it doesn't */
if(g_file_test(name_file,
G_FILE_TEST_EXISTS))
{
/*The image exists, we will first remove the previous image we had*/
gtk_container_remove(GTK_CONTAINER
(valorcitos->vbox),valorcitos->image);
g_print ("File found it is %s. \n",name_file);
/*We read and assign the desired image to our variable image*/
valorcitos->image=
gtk_image_new_from_file((gchar*)
name_file);
/*We remove the pervious label we had, since it would say that
the image was not found. */
gtk_container_remove(GTK_CONTAINER
(valorcitos->table),valorcitos->label);
/*We set the adequete value for our lable*/
valorcitos->label = g_object_new(GTK_TYPE_LABEL,
"label", "Ex:pumas.jpg or pics/1.jpg",
NULL);
/*we place our lable adequetely where it belonged*/
gtk_table_attach_defaults((GtkTable * )valorcitos->table,valorcitos->
label,0,1,2,3);
/*we show our lable*/
gtk_widget_show(valorcitos->label);
/*we place the image where it belongs*/
gtk_box_pack_start(GTK_BOX(
valorcitos->vbox),(valorcitos->image),FALSE, FALSE,0);
/*we show our image*/
gtk_widget_show(valorcitos->image);
}
/*the image that the user wanted to see was
not found*/
else
{
g_print ("File not found. \n");
/*we remove the lable we had, since we wnat to tell the user that the image was not found*/
gtk_container_remove(GTK_CONTAINER(
valorcitos->table),valorcitos->label);
/* we prepare the lable to say that the image was not found*/
valorcitos->label = g_object_new(GTK_TYPE_LABEL,
"label", "That image was not found!",
NULL);
/*we place the lable adequetly*/
gtk_table_attach_defaults((GtkTable * )valorcitos->table,valorcitos->
label,0,1,2,3);
gtk_widget_show(valorcitos->label);
/* we remove the previous image that we were displaying.*/
gtk_container_remove(GTK_CONTAINER(
valorcitos->vbox),valorcitos->image);
}
}
int main(int argc, char** argv)
{
/* we create a struct that will store the variables that we will use when the button is clicked.*/
struct values valorcitos;
/* We create the other GTK+ widgets which we will use */
GtkWindow* window;
GtkWidget *label;
GtkWidget *button;
/* Initialize the GTK+ library. */
gtk_init(&argc, &argv);
/* Create a window with window border width of 12 pixels and a
title text. */
window = g_object_new(GTK_TYPE_WINDOW,
"border-width", 12,
"title", "Image Viewer",
NULL);
/* Create the label widget. */
label = g_object_new(GTK_TYPE_LABEL,
"label", "Type in the address of the image:",
NULL);
/*Prepare the lable we will modify when the user clicks the button*/
valorcitos.label = g_object_new(GTK_TYPE_LABEL,
"label", "Ex:pumas.jpg or pics/1.jpg",
NULL);
/*prepare the textbox*/
valorcitos.entry=gtk_entry_new();
int text_width =5; // Width of field in characters
gtk_entry_set_width_chars(
GTK_ENTRY(valorcitos.entry), text_width);
/*prepare the image*/
valorcitos.image=gtk_image_new();
/*prepare the button*/
button=gtk_button_new_with_label("OK");
/* connect the signals to the button, when clicked we will
call the on_button_clicked function and send in the struct valorcitos
that stores the variables we need to manipulate* */
g_signal_connect (G_OBJECT(button), "clicked",
G_CALLBACK (on_button_clicked),&valorcitos);
/*We prepare a virtical box that will store a table and the image*/
valorcitos.vbox=gtk_vbox_new(FALSE,0);
/*we prepare a table that will store the textbox,lables and button*/
valorcitos.table= gtk_table_new(1,1,TRUE);
/*We pack the table with the variables */
gtk_table_attach_defaults ((GtkTable * )valorcitos.table,label,0,1,0,1);
gtk_table_attach_defaults ((GtkTable * )valorcitos.table,valorcitos.entry,0,1,1,2);
gtk_table_attach_defaults((GtkTable * )valorcitos.table,valorcitos.label,0,1,2,3);
gtk_table_attach_defaults((GtkTable * )valorcitos.table,button,1,2,1,2);
/*we add the table to the vbox*/
gtk_box_pack_start(GTK_BOX(
valorcitos.vbox),valorcitos.table, FALSE, FALSE, 0);
/*we add the image to the vbox*/
gtk_box_pack_start(GTK_BOX(
valorcitos.vbox),valorcitos.image,FALSE, FALSE, 0);
/* Pack the vbox into the window layout. */
gtk_container_add(GTK_CONTAINER(
window), GTK_WIDGET(valorcitos.vbox));
/* Show all widgets that are contained by the window. */
gtk_widget_show_all(GTK_WIDGET(
window));
/* Start the main event loop. */
g_print("main: calling gtk_main\n");
gtk_main();
/* Display a message to the standard output and exit. */
g_print("main: returned from gtk_main and exiting with success\n");
/* The C standard defines this condition as EXIT_SUCCESS, and this
symbolic macro is defined in stdlib.h (which GTK+ will pull in
in-directly). There is also a counter-part for failures:
EXIT_FAILURE. */
return EXIT_SUCCESS;
}
Con esto tenemos ya listo el codigo, y ahora sólo falta compilar y correrlo.
Para ellos, llevaremos acabo los siguientes pasos.
1)Correr Xephyr, para ello desde una terminal escribimos simplemente:
Xephyr :2 -host-cursor -screen 800x480x16 -dpi 96 -ac
Y se nos deberá abrir una ventanita negra.
2)Preparamos todo en scratchbox
-En otra terminal, escribimos /scratchbox/login
-Creamos el programa que ejutaremos: nano imagencitas.c
y alli pegaremos el código que acabamos de escribir.
- Compilamos el programa:
gcc -Wall -g imagencitas.c `pkg-config --cflags gtk+-2.0 gmodule-2.0` -o imagencitas `pkg-config --libs gtk+-2.0` `pkg-config --libs gmodule-2.0`
-Preparamos el ambiente para dibujar en el Xephyr :
En una consola escribimos: export DISPLAY=:2
af-sb-init.sh start
Y ahora simplemente con el siguiente comando correremos nuestro programa:
run-standalone.sh ./imagencitas
Y con esto deberíamos tener los siguiente:
Allí el usuario ha escrito que quiere ver la Imágen Pumas, pero aun no aprieta el botón.
Una vez que lo haya apretado tendríamos lo siguiente:
Y si el usuario escribiera el nombre de una imágen que no existe dentro del sistema, recibiría lo siguiente:
Y así es como, se podría crear una aplicación para ver imágenes en el n900.
Supongo que el código está medio sucio, pero es mi primera vez usando GTK y tengo además muchas otras responsabilidades...=(
Espero seguir jugando con esto, y mejorando.
Los dejo con la imágen de un comic, que me dió mucha risa: