23 January 2008

gtk.EntryCompletion

Esse é um tutorial que exige algum conhecimento de programação, da linguagem Python e do módulo PyGTK. Programadores experientes em outras linguagens provavelmente conseguirão entender e adaptar às suas necessidades. Caso queira aprender, existem tutoriais introdutórios de Python e PyGTK.

Para quem programa interfaces em PyGTK (ou GTK+ em outra linguagem, eu uso Python) aí vai uma dica de usabilidade:

Caso você tenha um campo de texto no seu programa, considere se não existe uma lista de valores comuns de preenchimento e dê uma ajudinha ao usuário a lembrar desses valores usando um gtk.EntryCompletion. Usá-lo é muito simples:
# Aqui eu pego uma gtk.Entry. Nesse caso peguei ela do
# meu xml que eu criei no glade

entry = xml.get_widget('entry_verbo')

# Depois crio os dois objetos necessários: um gtk.EntryCompletion,
# que vai desenhar a lista de sugestões e um gtk.ListStore que
# vai armazenar os valores.

completion = gtk.EntryCompletion()
list_store = gtk.ListStore(gobject.TYPE_STRING)

# Inserir uns valores. Note que são tuplas de um elemento só
# (por isso a vírgula sem nada depois). As tuplas inseridas
# seguem o modelo inicializado no construtor do ListStore.
# Nesse caso eu usei apenas um gobject.TYPE_STRING para dizer
# que minha lista guarda apenas uma string por registro

list_store.append(('aqui',))
list_store.append(('botamos',))
list_store.append(('umas',))
list_store.append(('palavras',))
list_store.append(('para',))
list_store.append(('testar',))

# Aqui eu associo a list_store ao meu completion criado anteriormente

completion.set_model(list_store)
completion.set_match_func(match_func)

# O método abaixo escolhe qual coluna do modelo vai conter o texto a
# ser mostrado no completion. Como só tem uma coluna no gtk.ListStore,
# vai ser essa que vamos usar.

completion.set_text_column(0)

entry.set_completion(completion)
Bom, a única coisa que falta no código acima é definir match_func que é uma função para buscar os valores de acordo com o que é digitado no gtk.Entry. Ela deve ser uma função com a seguinte assinatura
def match_func(completion, key_string, iter, func_data):
onde completion é o próprio objeto gtk.EntryCompletion usado pela função, key_string é a palavra que está no entry no momento da verificação, iter é um gtk.TreeIter que aponta para um item da lista de dados da gtk.EntryCompletion (uma gtk.ListStore, no caso do exemplo acima) e func_data é um argumento adicional que pode ser passado no método set_match_func do gtk.EntryCompletion.

Essa função será executada para cada item do gtk.ListStore e deve retornar True caso o item deva ser mostrado como opção de sugestão e False caso não deva. Na documentação da PyGTK a seguinte função está disponível como exemplo:
# Assumes that the func_data is set to the number of the text column in the
# model.

def match_func(completion, key, iter, column):
model = completion.get_model()
text = model.get_value(iter, column)
if text.startswith(key):
return True
return False
Ela cobre um dos usos mais comuns de um completion, que é mostrar as palavras na lista cujo início seja igual à palavra digitada. Um exemplo é mostrado na imagem abaixo:

1 comment:

Anonymous said...

Lendo o manual entendi que se faz necessário limpar o que havia sido
definido anteriormente, antes de atribuir a nova lista, conforme abaixo:

def set_model(model=None)

The set_model() method sets the gtk.TreeModel specified by model to be
used with the entry completion. A previously set model will be removed
before the new model is set. If model is None or not specified, the old
model will be unset.

O código abaixo funciona corretamente se eu não necessitar alterar o
conteúdo da lista.

No entanto, não funciona se o conteúdo da lista tiver que ser alterado.

Então, como fazer para redefinir?

--------
def autocompletar(self, entry, lista, coluna=0, caracter=1):

''' entry ----> gtk.Entry que deverá receber o recurso.
lista ----> Lista que será ligada ao entry.
coluna --> Número da coluna que usará o autocomplemento.
caracter -> A partir de quantos caracteres.
'''

completar = gtk.EntryCompletion()
completar.set_model(lista)
entry.set_completion(completar)
completar.set_text_column(coluna)
completar.set_minimum_key_length(caracter)

Antonio.