GTK+/O widget botão

Origem: Wikilivros, livros abertos por um mundo aberto.

Capítulo 7: O Widget Botão


Botões Normais[editar | editar código-fonte]

Nós vimos quase tudo que há para ver sobre os widgets botões. É bem simples. Há, entretanto, mais do que uma maneira de criar botões. Você pode usar gtk_button_new_with_label() ou gtk_button_new_with_mnemonic() para criar um botão com rótulo, usamos gtk_button_new_from_stock() para criar um botão com imagem e texto a partir de um item salvo ou gtk_button_new() para criarmos um botão vazio. É interessante enpacotarmos um rótulo ou um pixmap a este novo botão. Para fazermos isto, criamos uma nova caixa, e então empacotamos nossos objetos dentro da caixa usando o usual gtk_box_pack_start(), e então usamos gtk_container_add() para empacotar a caixa dentro do botão.

Aqui está um exemplo do uso do gtk_button_new() para criarmos um botão com uma imagem e um rótulo. Montamos o código para criamos uma caixa para que você possa usá-lo em seus programas esforço. Há mais exemplos do uso de imagens mais a frente neste tutorial.

#include <stdlib.h>
#include <gtk/gtk.h>

/* Create a new hbox with an image and a label packed into it
 * and return the box. */

static GtkWidget *xpm_label_box( gchar     *xpm_filename,
                                 gchar     *label_text )
{
    GtkWidget *box;
    GtkWidget *label;
    GtkWidget *image;

    /* Create box for image and label */
    box = gtk_hbox_new (FALSE, 0);
    gtk_container_set_border_width (GTK_CONTAINER (box), 2);

    /* Now on to the image stuff */
    image = gtk_image_new_from_file (xpm_filename);

    /* Create a label for the button */
    label = gtk_label_new (label_text);

    /* Pack the image and label into the box */
    gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 3);
    gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 3);

    gtk_widget_show (image);
    gtk_widget_show (label);

    return box;
}

/* Our usual callback function */
static void callback( GtkWidget *widget,
                      gpointer   data )
{
    g_print ("Hello again - %s was pressed\n", (char *) data);
}

int main( int   argc,
          char *argv[] )
{
    /* GtkWidget is the storage type for widgets */
    GtkWidget *window;
    GtkWidget *button;
    GtkWidget *box;

    gtk_init (&argc, &argv);

    /* Create a new window */
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

    gtk_window_set_title (GTK_WINDOW (window), "Pixmap'd Buttons!");

    /* It's a good idea to do this for all windows. */
    g_signal_connect (G_OBJECT (window), "destroy",
	               G_CALLBACK (gtk_main_quit), NULL);

    g_signal_connect (G_OBJECT (window), "delete_event",
	 	       G_CALLBACK (gtk_main_quit), NULL);

    /* Sets the border width of the window. */
    gtk_container_set_border_width (GTK_CONTAINER (window), 10);

    /* Create a new button */
    button = gtk_button_new ();

    /* Connect the "clicked" signal of the button to our callback */
    g_signal_connect (G_OBJECT (button), "clicked",
		       G_CALLBACK (callback), (gpointer) "cool button");

    /* This calls our box creating function */
    box = xpm_label_box ("info.xpm", "cool button");

    /* Pack and show all our widgets */
    gtk_widget_show (box);

    gtk_container_add (GTK_CONTAINER (button), box);

    gtk_widget_show (button);

    gtk_container_add (GTK_CONTAINER (window), button);

    gtk_widget_show (window);

    /* Rest in gtk_main and wait for the fun to begin! */
    gtk_main ();

    return 0;
}

A Função xpm_label_box() poderia ser usada para empacotar imagens e rótulos em qualquer widget que possa ser um container.

O widget botão possui os signais a seguir:

  • pressed - emitido quando um ponteiro de botão é pressionado dentro de um widget Botão.
  • released - emitido quando um ponteiro de botão é solto dentro de um widget Botão.
  • clicked - emitido quando um ponteiro de botão é pressionado e então solto dentro de um widget Botão.
  • enter - emitido quando um ponteiro entra no widget Botão.
  • leave - emitido quando um ponteiro deixa o widget Botão.

Botões de Chaveamento (Toggle Buttons)[editar | editar código-fonte]

Botões de Chaveamento (Toggle Buttons) são derivados de botões normais e são muito similares, exceto por eles estarem sempre em um de dois estados, alternados por um clique. Eles podem estar abaixados e, quando você clica novamente, voltam ao estado de emergido normal. Clicando novamente ele, voltará ao estado de abaixado.

Toggle Buttons são a base para os Botões de Selação (Check Buttons) e para os Radio Buttons, como tal, muitas das chamadas usadas para os Toggle Buttons são herdadas pelos Radio Buttons e Check Buttons. Aponteramos tais características, quando chegarmos a elas.

Criando um novo Toggle Button: ,

 GtkWidget *gtk_toggle_button_new( void );
 GtkWidget *gtk_toggle_button_new_with_label( const gchar *label );
 GtkWidget *gtk_toggle_button_new_with_mnemonic( const gchar *label );

Como você pode imaginar, essas funções são idênticas as funções de um botão normal. A primeira cria um botão vazio qualquer, e as duas ultimas criam um botão com um rótulo associado a eles. A variação _mnemonic() adicionalmente analisa o rótulo dos caracteres mnemônicos prefixados com '_'.

Para obter um estado de um Toggle Widget, incluindo Radio Buttons e Check Buttons, nós usamos o contrutor como mostrado em nosso exemplo abaixo. Isso testa o estado de nosso Toggle Button, pelo acesso do campo active da estrutura do Toggle Widget, depois primeio usa a macro GTK_TOGGLE_BUTTON para o cast do ponteiro do widget para um ponteiro específico de um Toggle Button. O sinal de interesse para nós emitido pelo toggle button (o toggle button, check button, e o radio button widgets) é o sinal "toggled". Para checar o estado desse botão, nós configuramos um sinal handler para capturar o sinal "toggled" e acessar a estrutura que determina esse estado. A função de chamada (callback) irá parecer algo semelhante a isso:

 void toggle_button_callback (GtkWidget *widget, gpointer data)
 {
     if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) 
     {
         /* If control reaches here, the toggle button is down */
   
     } else {
   
         /* If control reaches here, the toggle button is up */
     }
 }

Para forçar o estado de um toggle button, e seus filhos, os radios e os botões de checagem, use esta função:

 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
                                    gboolean        is_active );

A Chamada acima pode ser usada para configurar o estado do toggle button, e seus filhos radio buttons e botões de checagem. Passando como primeiro argumento do botão criado, e TRUE ou FALSE, como segundo argumento para especificar se deve estar abaixado (acionado) ou levantado (liberado). O Padrão é levantado, ou FALSE.

Note que quando você usa a função gtk_toggle_button_set_active() e o estado é efetivamente, isso causa um sinal "clicked" e "toggled" para ser emitido atráves do botão.

 gboolean gtk_toggle_button_get_active	(GtkToggleButton *toggle_button);

Isso retorna o estado atual do toggle button como um valor booleano TRUE ou FALSE.

Botões de Checagem (Check Buttons)[editar | editar código-fonte]

Botões de Checagem (Check Buttons) herdam muitas propriedades e funções dos Toggles Buttons acima, mas se parecem um pouco diferente. Em vez de serem botões com textos, eles são pequenos quadrados com textos ao lado. Eles são geralmente usados para marcar e desmarcar opções em uma aplicação.

A Função de criação são similares aos botões normais.

 GtkWidget *gtk_check_button_new( void );
 GtkWidget *gtk_check_button_new_with_label ( const gchar *label );
 GtkWidget *gtk_check_button_new_with_mnemonic ( const gchar *label );

A Função gtk_check_button_new_with_label() cria um Check Button com um texto ao seu lado.

Checar o estado de um Check Button é semelhante a checagem do Toggle Button.

Radio Buttons[editar | editar código-fonte]

Radio Buttons são similares aos check buttons exceto pelo fato que eles são agrupados logo somente um deles pode ser selecionado naquele instante. Isso é interessante para a sua aplicação quando você precisa selecionar uma opção entre várias outras.

Criar um novo Radio Button é possível com uma destas chamadas:

 GtkWidget *gtk_radio_button_new( GSList *group );
 GtkWidget *gtk_radio_button_new_from_widget( GtkRadioButton *group );
 GtkWidget *gtk_radio_button_new_with_label( GSList *group,
                                             const gchar  *label );
 GtkWidget* gtk_radio_button_new_with_label_from_widget( GtkRadioButton *group,
                                                         const gchar    *label );
 GtkWidget *gtk_radio_button_new_with_mnemonic( GSList *group,
                                                const gchar  *label );
 GtkWidget *gtk_radio_button_new_with_mnemonic_from_widget( GtkRadioButton *group,
                                                            const gchar  *label );

Você notará o argumento extra para essas chamadas. Eles requerem um grupo para desempenhar sua principal propriedade. Na primeira chamada a gtk_radio_button_new() ou gtk_radio_button_new_with_label() devemos passar NULL como o primeiro argumento. E então criar um grupo usando:

 GSList *gtk_radio_button_get_group( GtkRadioButton *radio_button );

Um detalhe importante a ser lembrado é que gtk_radio_button_get_group() deve ser chamado para cada novo botão adicionado ao grupo, com o botão anterior passado como argumento. O resultado é então passado a nova chamada gtk_radio_button_new() or gtk_radio_button_new_with_label(). Isso permite uma sequência de botões a serem estabelecidos.

Você pode encurta isto levemente com o uso da sintaxe a seguir, na qual é removida a necessidade por uma variável exclusiva aos botões.

 button2 = gtk_radio_button_new_with_label(
                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button1)),
                  "button2");

A variante da função de criação _from_widget() permite encurtar o código mais ainda, omitindo a chamada a função gtk_radio_button_get_group(). Esse formato é usado no exemplo da criação do terceiro botão:

 button2 = gtk_radio_button_new_with_label_from_widget(
 	         GTK_RADIO_BUTTON (button1), 
                  "button2");

É também uma boa ideia configurarmos qual botão será setado inicialmente com:

 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
                                    gboolean        state );

Isso é descrito na seção dos Toggled Buttons, e funciona exatamente da mesma forma. Uma vez que os Radios Buttons estão agrupados, somente um deles pode ser ativado naquele instante. Se um usuário clicar em um botão em dado instante e posteriormente clicar em outro, o primeiro botão irá emitir um sinal de "toggled" (para reportar a desativação) e depois o segundo botão também irá emitir um sinal de "toggled" (avisando que está ativo).

O próximo exemplo cria um grupo de Radio Buttons com três botões.

 #include <glib.h>
 #include <gtk/gtk.h>

 static gboolean close_application( GtkWidget *widget,
                                    GdkEvent  *event,
                                    gpointer   data )
 {
   gtk_main_quit ();
   return FALSE;
 }
  
 int main( int   argc,
           char *argv[] )
 {
     GtkWidget *window = NULL;
     GtkWidget *box1;
     GtkWidget *box2;
     GtkWidget *button;
     GtkWidget *separator;
     GSList *group;
      
     gtk_init (&argc, &argv);    
      
     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
         
     g_signal_connect (window, "delete-event",
   		        G_CALLBACK (close_application),
                       NULL);
 
     gtk_window_set_title (GTK_WINDOW (window), "radio buttons");
     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
 
     box1 = gtk_vbox_new (FALSE, 0);
     gtk_container_add (GTK_CONTAINER (window), box1);
     gtk_widget_show (box1);
 
     box2 = gtk_vbox_new (FALSE, 10);
     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
     gtk_widget_show (box2);
 
     button = gtk_radio_button_new_with_label (NULL, "button1");
     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
     gtk_widget_show (button);
 
     group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
     button = gtk_radio_button_new_with_label (group, "button2");
     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
     gtk_widget_show (button);
 
     button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (button),
	                                                  "button3");
     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
     gtk_widget_show (button);

     separator = gtk_hseparator_new ();
     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
     gtk_widget_show (separator);

     box2 = gtk_vbox_new (FALSE, 10);
     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
     gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
     gtk_widget_show (box2);
 
     button = gtk_button_new_with_label ("close");
     g_signal_connect_swapped (button, "clicked",
                               G_CALLBACK (close_application),
                               window);
     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
     gtk_widget_set_can_default (button, TRUE);
     gtk_widget_grab_default (button);
     gtk_widget_show (button);
     gtk_widget_show (window);
      
     gtk_main ();
 
     return 0;
 }

Notas e Referências[editar | editar código-fonte]

Capítulo traduzido do Original: The Button Widget