Arquivo para Janeiro, 2008

File selector em Python + Tkinter

Antes de partir para a violência e decidir programar uma biblioteca própria, decidi tentar usar duas bibliotecas conhecidas: PyGTK e Tkinter, que é uma abstração simples sob o Tcl/Tk para Python.

Não tenho opinião formada sobre o PyGTK, até porque não consegui sequer usá-lo. Apesar de seguir as instruções de instalação à risca, o Python sempre acusa um erro críptico ao tentar importar uma das bibliotecas necessárias.

O Tkinter, como já disse antes, é uma camada simples sob o Tcl/Tk. Desta forma, não espere nada que lembre a simplicidade de Python. Na verdade, há muita magia-negra envolvida. Até para abrir um file selector você tem que fazer o bind manual das ações “Ok” e “Cancel”. Está bem que algum cidadão poderia querer que o botão “Ok” fizesse mais alguma coisa além de confirmar a escolha, mas a falta de uma opção padrão me faz sentir como se ainda estivéssemos em 1997.

E não preciso nem falar sobre a “documentação”. Exemplos intuitivos de uso? Hah!

Apesar dos pesares, o Tkinter tem algumas funcionalidades que dariam um bom trabalho se eu decidisse implementá-las. Assim, o usarei para alguns itens específicos, como para selecionar um arquivo para edição.

Para ajudar a manter minha sanidade, implementei mais uma camada acima do Tkinter, que implementa um seletor de arquivos. Eu queria algo que permitisse que eu usasse apenas um método para selecionar um arquivo. Algo como:

caminho_do_arquivo = open_file_selector()

O resultado é:

# Wrapper for the Python's Tix ExFileSelector dialog. It handles
# the annoying handle assignment and TK black magic, offering
# a bare-bones OO file selector implementation.
#
# Author: Paolo Victor, paolovictor@gmail.com
import Tix
from Tkinter import *
from Tkconstants import *

class TKSelector:
    def __file_selected__(self, path):
        # Sets path, closes window
        self.__path__ = path
        self.__root__.destroy()

    def __cancel_button_clicked__(self, action):
        # Unsets path, closes window
        self.__path__ = None
        self.__root__.destroy()

    def open(self, title="Select a file", baseDir=None):
        # Resetting path
        self.__path__ = None

        # Initializing root panel
        self.__root__ = Tix.Tk()
        self.__root__.wm_resizable(0, 0)
        self.__root__.wm_title(title)

        # Initializing  selector
        self.__selector__ = Tix.ExFileSelectBox(self.__root__)
        self.__selector__.cancel.bind("", self.__cancel_button_clicked__)        

        configuration = {"command": self.__file_selected__}
        if baseDir: configuration["dir"] = baseDir
        self.__selector__.configure(configuration)

        self.__selector__.pack()

        # Displaying selector
        self.__selector__.mainloop(0)

        return self.__path__

# Convenience method =]
def open_file_selector(title="Select a file", baseDir=None):
    selector = TKSelector()
    return selector.open(title, baseDir)

É no mínimo irônico que eu tenha reclamado da documentação do Tkinter, para logo depois mostrar um código pouco documentado :) , mas entendo que os nomes das variáveis são auto-descritivos.

Exemplo de uso, se o código estiver em um módulo chamado “utils”:

import utils

caminho_do_arquivo = utils.open_file_selector("Selecione um arquivo")

Este código abre um seletor de arquivos com o título “Selecione um arquivo”, cujo caminho inicial é o diretório de execução do processo e que retorna o nome do arquivo, se este for selecionado, ou “None”, se a seleção foi cancelada.

Comentários (1)