sexta-feira, 19 de setembro de 2008

Como preencher uma GtkComboBox criada no GLADE

.
Penei com isso ontem um tempão. A GTK tem a função gtk_combo_box_append_text() (entre outras) com o objetivo de facilitar a criação de drop-downs de texto. Porém para usar esta função, o drop-down (GtkComboBox) tem que ter sido criado via gtk_combo_box_new_text() , o que parece não ser o caso dos drop-downs criados via Glade. Na net, encontrei muita referência disso para outras linguagens (PHP por exemplo), mas nada para o velho e bom C... Felizmente, após muita procura, encontrei um pedaço de código que resolveu meu problema. Coloco ele aqui, comentado, na esperança de ajudar outros "desesperados" como eu ... :-)

Em linhas gerais, você precisa criar uma GtkListStore, para armazenar a lista de itens que vai aparecer no drop-down. Depois, associe esta lista ao drop-down, e finalmente defina COMO esta lista vai aparecer na tela ("ser renderizada"). UFA! Bem que podia ter uma opção no GLADE para escolher como o drop-down vai ser criado na hora do uso, se via gtk_combo_box_new_text para simples drop-downs de texto, ou da forma default, para drop-downs mais elaboradas.

No código abaixo, a variável "drop_bds" é um GtkWidget*, e contém minha drop-down (GtkComboBox).

[ OBS!! Sugiro que você copie o programa abaixo e cole em um editor de texto-puro, para melhor visualização da identação e dos comentários linha-a-linha. Não sei como colocar aquela janelinha de código que se encontra em blogs por aí, se alguém puder me ajudar, agradeço! ]

// um GtkComboBox implementa a GtkCellLayout. O comando abaixo apaga este layout.
// Precisei fazer isso porque o conteúdo do meu drop-down é o resultado do click em um botão.
// Se eu não apagar o layout logo no início, cada vez que aperto o botão o drop-down vai
// crescendo, pois vai mantendo o layout anterior e adicionando o novo.

gtk_cell_layout_clear(GTK_CELL_LAYOUT(drop_bds));


// outras variaveis necessarias:

// inteiro, para ir contando os elementos que vamos inserir no drop-down
int cont;

// a GtkListStore que vai armazenar os elementos do drop-down
GtkListStore *list_store;

// o "renderizador" que vai mostrar o conteúdo da lista dentro do drop-down
GtkCellRenderer *renderer;

// um iterador, uma espécie de ponteiro que indica em que lugar da lista
// vamos inserir o novo conteúdo
GtkTreeIter iter;


// cria a GtkListStore, com apenas 1 coluna, conteúdo do tipo string
list_store = gtk_list_store_new (1, G_TYPE_STRING);


// laço que vai preencher a lista com as strings que vão compor o drop-down:

for(cont=0; cont < ...numero de elementos a inserir... ; cont++)
{

// string que vai armazenar o texto a ser inserido no drop-down
char conteudo[50];

// defina o conteudo da string acima
// no meu caso, a string seria uma combinacao de outras strings e outros dados,
// provenientes de outras partes do programa. Optei por usar a função sprintf para
// "montar" essa string. Veja o que é melhor no seu caso!

sprintf(conteudo, "%s", ...o conteudo que voce quer na string... );


// Adiciona uma linha ( VAZIA! ) na lista (list_store), e faz o iterador (variável iter)
// apontar para ela, para que depois possamos "encher" essa linha vazia de conteúdo

gtk_list_store_append (list_store, &iter);

// armazena um valor na lista, na linha apontada por iter, nas colunas indicadas.
// A lista de colunas termina com um -1. Como só tenho 1 coluna na minha lista, fica:
// 0 (primeira e única coluna) , conteudo (a string a inserir nessa linha) , -1 (fim!)

gtk_list_store_set (list_store, &iter, 0, conteudo, -1);
}


// insere a lista que acabamos de montar dentro do drop-down:
gtk_combo_box_set_model(GTK_COMBO_BOX(drop_bds), GTK_TREE_MODEL(list_store));

//
// falta agora definir como essa lista irá aparecer na tela, isto é, ser renderizada.
//

// criação de um renderizador de textos:
renderer = gtk_cell_renderer_text_new();

// insere o renderizador criado no drop-down
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(drop_bds), renderer, TRUE);

// define as propriedades (atributos) deste renderizados. Lista-se cada propriedade
// e terminamos a lista com um NULL
// Neste caso, estamos definindo a propriedade "text" e seu valor 0 (não consegui encontrar na
// documentação da API os atributos possíveis e seus valores.... alguém me ajuda nisso?)
gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(drop_bds), renderer, "text", 0, NULL);

// até aqui está pronto, seu drop-down estará com o conteúdo desejado.

// no meu caso, eu quero mostrar ao usuário que agora temos dados
// no drop-down para ele escolher
// (a primeira vez que o usuário vê minha janela, o drop-down está vazio)
// Desta forma, vou usar um comando para tornar o primeiro item do
// drop-down como item ativo.

gtk_combo_box_set_active(GTK_COMBO_BOX(drop_bds), 0);



Pronto. Divirtam-se!

Grande abraço a todas e a todos!
Carlão

4 comentários:

icarooo disse...

grande dica, seu texto caiu como uma luva, ja faziam 2 semanas que eu estava tentando colocar textos dentro de uma combobox, foi mais dificil do que criar um LFS, mas agora foi, muito obrigado

Carlos José disse...

Oi Icarooo,
Que legal que você gostou! Fique de olho, em breve teremos outras postagens relacionadas com gtk e glade.
Abraços!
Carlão

Ronaldo disse...

Excelente artigo. Consegui entender mais claramente. Mas quando uso tento preenher acambo aparece: (lixogtk:7674): GLib-GObject-WARNING **: invalid cast from `GtkButton' to `GtkComboBox'
POde me ajudar?

Carlos José Pereira disse...

Oi Ronaldo,
Estou afastado da programação GTK desde o doutorado (final de 2008, mais ou menos a data da postagem), então não tenho como te ajudar neste momento. Pretendo retomar a programação GTK neste ano, fique de olho no blog, em breve devo recomeçar as postagens.
Grande abraço!
Carlão