Ventanas

De Wiki GNOME Chile
Saltar a: navegación, buscar

Las ventanas son la parte básica de todo interfaz, pues es el widget sobre el que se muestra el interfaz de la aplicación al usuario.

Las ventanas, todas ellas, derivan de la clase GtkWindow, que a su vez deriva de GtkContainer. Por tanto, se puede decir que las ventanas son un caso de contenedores especial, pues son contenedores que no están contenidos en ningún otro contenedor, como si que ocurre con el resto de contenedores comentados en el apartado anterior.


Contenido

Ventanas (GtkWindow)

GtkWindow es el objeto ventana de nivel más alto, puede contener a otros widgets.

gtk_window_new() crear un nuevo objeto GtkWindow, que normalmente será una ventana del nivel más alto (el tipo de la ventana debería de ser GTK_WINDOW_TOPLEVEL). Si estás implementando algo como un menu pop-up desde cero (una mala idea, sería mejor que usar GtkMenu), podrías usar el parámetro GTK_WINDOW_POPUP. GTK_WINDOW_POPUP no está diseñado para cuadros de diálogo, aunque en otros toolkits llaman "popups" a los cuadros de diálogo. En GTK+, GTK_WINDOW_POPUP significa un menú pop-up o una ventanita tooltip. En X11, las ventanas popup no se controlan por el gestor de ventanas.

Si lo que quieres símplemente es quitar la decoración de una ventana (ventanas sin bordes), usa la función gtk_window_set_decorated(), no uses GTK_WINDOW_POPUP.


Diálogos (GtkDialog)

Los diálogos son ventanas temporales, que se usan para obtener o mostrar determinada información del/al usuario. Habitualmente son ventanas que estan activas durante un espacio de tiempo limitado, el que tarda el usuario en actuar ante lo que se le indica en el cuadro de diálogo. Ejemplos típicos de diálogos son una ventana para confirmar una acción con el usuario, para mostrar un mensaje de error, etc. Creación de diálogos

En GTK+, la creación de diálogos se hace con GtkDialog, que contiene dos funciones para la creación de los mismos:

    GtkWidget* gtk_dialog_new (void);
    GtkWidget* gtk_dialog_new_with_buttons (const gchar *title,
                                            GtkWindow *parent,
                                            GtkDialogFlags flags,
                                            const gchar *first_button_text,
                                            ...);


La primera función crea un diálogo completamente vacío, sin botones, y sin ningun contenido. La segunda, nos permita especificar distintas propiedades del diálogo en el momento de su creación.

Con gtk_dialog_new, la creación del diálogo consta de dos pasos. Uno es la creación del diálogo vacío, lo cual se realiza con una llamada a gtk_dialog_new, mientras que el otro consiste en añadir los botones al mismo. Un ejemplo típico de esto sería:

    GtkWidget *dialog;

    dialog = gtk_dialog_new ();
    gtk_dialog_add_button (GTK_DIALOG (dialog), "Cerrar", GTK_RESPONSE_CLOSE);


Esta nueva función, gtk_dialog_add_button, añade un nuevo botón al diálogo, en su parte inferior derecha. A cada botón es necesario asociarle tanto una cadena de texto ("Cerrar" en el ejemplo anterior), que será el texto que se muestre dentro del botón, y un código de respuesta, que permite identificar el botón pulsado, como se verá más adelante. Estos códigos de respuesta son denominados “responses” (respuestas), y se incluyen unos cuantos por defecto, tales como GTK_RESPONSE_CLOSE, aunque, por supuesto, se pueden definir nuevos códigos.

Como se comentaba anteriormente, gtk_dialog_new_with_button permite hacer todo lo anteriormente expuesto en un solo paso. Es decir, crear el diálogo con botones directamente, sin necesidad del paso adicional. Aparte de especificar la lista de botones a crear en el diálogo, esta función permite especificar el título de la ventana y la ventana padre del diálogo, así como distintas opciones de creación del diálogo. Así, se podría crear el mismo diálogo explicado anteriormente con el siguiente código:

    GtkWidget *dialog;
    GtkWindow *parent_window;

    dialog = gtk_dialog_new_with_buttons ("Título del diálogo",
                                          parent_window,
                                          0,
                                          "Cerrar", GTK_RESPONSE_CLOSE,
                                          NULL);


gtk_dialog_new_with_buttons usa una lista variable de argumentos. Los primeros son fijos, mientras que los últimos especifican la lista de botones a crear, todos ellos identificados con dos parámetros, como en el caso anterior: texto a mostrar en el botón y código de respuesta. El último parámetro debe ser siempre NULL, que marca el fin de la lista de botones.

Se podría usar esta misma función para crear varios botones de la siguiente forma:

    GtkWidget *dialog;
    GtkWindow *parent_window;

    dialog = gtk_dialog_new_with_buttons ("Título del diálogo",
                                          parent_window,
                                          0,
                                          "Aceptar", GTK_RESPONSE_OK,
                                          "Cancelar", GTK_RESPONSE_CANCEL,
                                          NULL);


Esto crearía un diálogo con dos botones. Por supuesto, se puede extender este ejemplo y añadir cuantos botones sean necesarios, siempre y cuando cada uno de ellos esté correctamente identificado (texto y código de respuesta asociados) y que el último parámetro sea NULL.

Una vez está creado el diálogo, es momento de añadirle contenido. Para ello, se usa un widget interno de la GtkDialog, que no es más que un GtkBox en el que se pueden añadir los distintos widgets que forman el diálogo.

GTK+ trata las cajas de diálogo como una ventana dividida verticalmente en dos partes. La sección superior es una GtkVBox, y es donde se pueden colocar widgets como GtkLabel o GtkEntry. El área inferior es conocida como action_area. Se usa normalmente para empaquetar botones como "cancelar", "ok" o "aplicar" en el diálogo. Las dos áreas están separadas por un widget GtkHSeparator.

Se puede acceder a las partes superior e inferior de un nuevo 'dialogo' mediante GTK_DIALOG(dialog)->vbox y GTK_DIALOG(dialog)->action_area, como se puede ver en el ejemplo siguiente. También se pueden crear diálogos modales (es decir, un diálogo que bloquea el resto de la aplicación hasta que el usuario responda a lo que se le pide en el diálogo) mediante una llamada a gtk_window_set_modal() en el propio diálogo. Se debe usar la macro GTK_WINDOW() para convertir el tipo del widget devuelto por gtk_dialog_new() a una GtkWindow. Si se usa gtk_dialog_new_with_buttons() también se puede pasar el flag GTK_DIALOG_MODAL como argumento para construir un diálogo modal.

#include "gtk/gtk.h"

gint delete_event( GtkWidget *widget,
                   GdkEvent  *event,
                   gpointer   data )
{
        gtk_main_quit ();
        return FALSE;
}


/* Función para abrir una caja de diálogo que muestre un mensaje dado como parámetro. */

void quick_message (gchar *message, GtkWidget *parent) {

   GtkWidget *dialog, *label;

   /* Create the widgets */

   dialog = gtk_dialog_new_with_buttons ("Título del cuadro de diálogo",
                                         GTK_WINDOW (parent),
                                         GTK_DIALOG_DESTROY_WITH_PARENT,
                                         GTK_STOCK_OK,
                                         GTK_RESPONSE_NONE,
                                         NULL);
   label = gtk_label_new (message);

   /* Ensure that the dialog box is destroyed when the user responds. */

   g_signal_connect_swapped (GTK_OBJECT (dialog),
                             "response",
                             G_CALLBACK (gtk_main_quit),
                             GTK_OBJECT (dialog));

   /* Add the label, and show everything we've added to the dialog. */

   gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
                      label);
   gtk_widget_show_all (dialog);
}



int main( int   argc,
          char *argv[])
{
        GtkWidget *window;

        gtk_init (&argc, &argv);

        /* Crea una ventana */
        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

        /* Siempre se debe conectar la señal delete_event a la ventana
         * principal, para así poder cerrarla.  */
        g_signal_connect (G_OBJECT (window), "delete_event",
                          G_CALLBACK (delete_event), NULL);
        gtk_container_set_border_width (GTK_CONTAINER (window), 10);

        quick_message("Mensaje en una botella.", window);

        /* La función principal. */
        gtk_main ();

        /* El control vuelve aquí cuando se llama a gtk_main_quit(), pero no cuando
         * se usa exit(). */

        return 0;
}


Ventanas de mensaje (GtkMessageDialog)

GtkMessageDialog muestra un diálogo con una imagen que representa el tipo de mensaje (Error, Pregunta, etc.) además de algún texto aclaratorio. Es símplemente un widget para facilitar el trabajo; se puede construir la ventana equivalente a la ofrecida por GtkMessageDialog sin mucho esfuerzo, pero GtkMesageDialog nos ahorrará teclear código en balde. La forma más sencilla de crear un diálogo modal consiste en usar gtk_dialog_run(), aunque es posible hacerlo también pasando el parámetro GTK_DIALOG_MODAL, gtk_dialog_run() construirá automáticamente el diálogo modal y esperará a que el usuario responda a lo indicado. gtk_dialog_run() devolverá el control cuando el usuario pulse cualquiera de los botones del cuadro de diálogo.

Ejemplo de un cuadro de diálogo modal.

 dialog = gtk_message_dialog_new (main_application_window,
                                  GTK_DIALOG_DESTROY_WITH_PARENT,
                                  GTK_MESSAGE_ERROR,
                                  GTK_BUTTONS_CLOSE,
                                  "Error loading file 's': s",
                                  filename, g_strerror (errno));
 gtk_dialog_run (GTK_DIALOG (dialog));
 gtk_widget_destroy (dialog);


También puedes construir un cuadro de diálogo no-modal GtkMessageDialog como sigue:

 dialog = gtk_message_dialog_new (main_application_window,
                                  GTK_DIALOG_DESTROY_WITH_PARENT,
                                  GTK_MESSAGE_ERROR,
                                  GTK_BUTTONS_CLOSE,
                                  "Error loading file 's': s",
                                  filename, g_strerror (errno));

 /* Destruir el diálogo cuando el usuario pulse un botón */
 g_signal_connect_swapped (GTK_OBJECT (dialog), "response",
                           G_CALLBACK (gtk_widget_destroy),
                           GTK_OBJECT (dialog));


Ventanas invisibles (GtkInvisible)

GtkInvisible es un widget usado internamente por GTK+ que no será mostrado en pantalla. Probablemente, no sea útil para los desarrolladores de aplicaciones. Es usado por GTK+ para la correcta gestión del puntero del ratón y gestión de selecciones en el código interno de arrastrar-y-soltar ("drag-and-drop").

La gestión del puntero del ratón se usa en operaciones que necesitan de un completo control sobre los eventos originados por el ratón, incluso si el puntero del ratón deja la aplicación (para pasar a otra). Por ejemplo en GTK+ se usa para el control de Drag and Drop, para arrastrar el manejador en los widgets GtkHPaned y GtkVPaned y para cambiar el tamaño de las columnas en los widgets GtkCList.

Ofrece los siguientes métodos:

GtkWidget*  gtk_invisible_new               (void);
GtkWidget*  gtk_invisible_new_for_screen    (GdkScreen *screen);
void        gtk_invisible_set_screen        (GtkInvisible *invisible,
                                             GdkScreen *screen);
GdkScreen*  gtk_invisible_get_screen        (GtkInvisible *invisible);


Ventanas embebidas (GtkPlug)

Junto a GtkSocket, GtkPlug ofrece la posibilidad de incrustar widgets de un proceso en otro proceso diferente de una forma transparente al usuario. Un proceso creará un widget GtkSocket y pasará el ID de la ventana de ese widget a otro proceso, que posteriormente creará un GtkPlug tomando como parámetro el ID recogido. Cualquier widget contenido en el GtkPlug aparecerá entonces en la ventana de la primera aplicación.

GtkPlug ofrece los siguientes métodos:

void        gtk_plug_construct              (GtkPlug *plug,
                                             GdkNativeWindow socket_id);
void        gtk_plug_construct_for_display  (GtkPlug *plug,
                                             GdkDisplay *display,
                                             GdkNativeWindow socket_id);
GtkWidget*  gtk_plug_new                    (GdkNativeWindow socket_id);
GtkWidget*  gtk_plug_new_for_display        (GdkDisplay *display,
                                             GdkNativeWindow socket_id);
GdkNativeWindow gtk_plug_get_id             (GtkPlug *plug);


El ID de ventana del socket se obtiene usando gtk_socket_get_id(). Antes de usar esta función, el socket debe haber sido puesto a la vista "realize", y por tanto, debe haber sido añadido a su padre.

Ejemplo. Cómo obtener el ID de ventana de un socket.

GtkWidget *socket = gtk_socket_new ();
gtk_widget_show (socket);
gtk_container_add (GTK_CONTAINER (parent), socket);

/* The following call is only necessary if one of
 * the ancestors of the socket is not yet visible.
 */
gtk_widget_realize (socket);
g_print ("The ID of the sockets window is %x\n",
         gtk_socket_get_id (socket));


Obsérvese que si se pasa el ID de ventana del socket a otro proceso que se conecte (plug) a dicho socket, debemos asegurarnos de que el widget socket no sea destruído hasta que se cree la conexión. La violación de esta regla puede causar efectos impredecibles, siendo el más probable que la ventana plug aparezca como una ventana separada.

Se puede comprobar que la conexión ha sido creada examinando el campo plug_window de la estructura GtkSocket. Si este campo es distinto a NULL, la conexión con el socket se habrá creado satisfactoriamente.

Cuando GTK+ reciba la notificación de que la ventana incrustada ha sido destruída, destruirá el socket automáticamente. Por lo tanto, el programador debe estar preparado para tratar la destrucción del socket en cualquier momento dentro del bucle main principal.

La comunicación entre GtkSocket y GtkPlug sigue las normas impuestas por el protocolo XEmbed. Este protocolo ha sido así mismo implementado en otros toolkits de desarrollo como Qt, permitiendo el mismo nivel de integración al incrustar un widget Qt en GTK o viceversa.

Un socket también puede ser usado para incrustar cualquier ventana pre-existente de primer nivel usando la función gtk_socket_steal(), aunque el grado de integración cuando se realiza esta operación no es tan bueno como cuando se usa GtkPlug en conjunto con GtkSocket.


Grupos de ventanas (GtkWindowGroup)

Un GtkWindowGroup se define para limitar el efecto del seguimiento del puntero del ratón entre ventanas. GtkWindowGroup deriva directamente de GObject y ofrece los siguientes métodos:

    GtkWindowGroup* gtk_window_group_new (void);


Crea un nuevo objeto GtkWindowGroup. Los seguimientos añadidos con gtk_grab_add() sólo afectan a las ventanas dentro del mismo GtkWindowGroup.

    void gtk_window_group_add_window  (GtkWindowGroup *window_group,
                                       GtkWindow *window);
    void gtk_window_group_remove_window (GtkWindowGroup *window_group,
                                         GtkWindow *window);

Herramientas personales
Espacios de nombres

Variantes
Acciones
Navegación
Herramientas