Embutindo imagens nos scripts Python para aplicações Tkinter

Arquivos gráficos geram uma dependência na aplicação cujo tratamento (de existência ou MD5) pode não valer a pena dependendo do tamanho da aplicação. O que fazer para evitar que o usuário exclua, renomeie, corrompa ou modifique um arquivo de imagem? Este artigo visa introduzir uma solução para este problema.

[ Hits: 26.032 ]

Por: Willie Lawrence em 26/12/2014


Criando uma aplicação básica



Um aplicativo básico em Tkinter seria:

from Tkinter import *
top = Tk()
button_image = PhotoImage(file="images/okbutton.gif") # aponta para o caminho no disco rígido
ok_button = Button(top, text="ok",image=button_image,compound=LEFT)
ok_button.grid()
top.mainloop()

Esse formato de aplicativo é o mais comum, mas está sujeito a uma série de adversidades como:
  1. O usuário exclui o arquivo da pasta: o script dará um erro na terceira linha
  2. O usuário muda o nome do arquivo: o script dará um erro na terceira linha
  3. O usuário corrompe o arquivo: o script dará um erro na terceira linha
  4. O usuário edita a imagem num editor: o design da sua aplicação pode ser desconfigurado

Para resolver esses problemas existe um recurso poderoso, porém pouco utilizado: o parâmetro "data". Assim como páginas HTML e CSS é possível embutir imagens em diversos formatos no script Python utilizando o Here Document (wikipedia).

Com o Here Document é possível referenciar uma imagem que não está no disco rígido, mas sim dentro da própria aplicação, como um dado constante. Da mesma forma que HTML e CSS (usando DataURI) a imagem precisa estar encodificada no formato base64. Dessa forma o script apresentado anteriormente ficaria mais ou menos assim:

from Tkinter import *
top = Tk()
IMAGE = ""
button_image = PhotoImage(data=IMAGE)
ok_button = Button(top, text="ok",image=button_image,compound=LEFT)
ok_button.grid()
top.mainloop()

Com esse formato a imagem se transforma numa string constante que pode ser organizada num novo módulo ou ser persistida com shelve (picke) ou mesmo num banco de dados. Existem muitas opções online para converter sua imagem para base64. Podemos citar:
Mas também podemos utilizar a biblioteca base64 do próprio Python:

import base64
my_image_file = open("meuarquivo.png", "rb") # le o arquivo no modo binario
file_content = my_image_file.read() # le o conteudo do arquivo
my_image_file.close()
IMAGE_ENCODED = base64.b64encode(file_content) # encodifica na base64
# entao criamos o arquivo com a imagem no formato base64
output = open("image.txt","w")
output.write(IMAGE_ENCODED)
output.close()

Depois de criado o arquivo de texto, podemos colocar a imagem no nosso script anterior. Como exemplo vou utilizar uma imagem que está disponível neste endereço utilizando o Python Image Library - PIL:

from Tkinter import *
import base64
import ImageTk # importa o PIL
top = Tk()
IMAGE = "iVBORw0KGgoAAAANSUhEUgAAADcAAAA3CAYAAACo29JGAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29\
mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJsSURBVHja7JrrbYMwEIAvqAu4I7Qj0BHMCGQEGAF\
GgBGaEcIIZYRkBVZgBArSIbmubTAPc0Y56X7EhITP9wYuXdfBWSWAE8sl/D4Vz0DT9Fo+kg7eTgIVIxj\
rte21GiB9h2MIFQtrFVrPa8uJ1gK0WIpw4DPcXbLWs9fraDFfs2XY60Phhl8ymG9wMYKFwlqOFlOKL25\
Z9JpJa1Gvtekk6nAM44sLaw1a6zl1MmW4DwQLJbBIFV8+wQ1AP0KaHzNihCnf296SY+JYBUYRjqPFRKk\
x1be2P0YJLtGARb6PPAm2UqDoOrye53Rg0RJXpAQXK8DGOtau/fHg4ORxl9ZamzpGFS5UJA/YEuwoOB3\
YrJaKMtzYUjFpPReHTF/h7ggI0jxW7vFngWOwcOtaRgEuk6bnMTNe9/xTF3AxDpuypFtmxiPgPhRFGjD\
Gqr13NXAQZ0wRZ7mLWAgUY/0QHx2qKrvZ3PcIXceZbhLnip2O8QJtO4cY/t/QGd2xcQUXSLMU08SN7ph\
NnO1Wz0xwDLWZuOBsRZy1ruJMhmtxRz8ndjZTxNDc7zh1R11CyScAiwnrqo7Xrt3RVApyQ3fO4e8NUlF\
0jzFzOEh0de464XqqNa5xxyc1uMbgSlyKK12yaY9yxzkdSmm4j5FIVmOW5x8OZ9r5BIG4BDrH8iTgBrl\
NWK8wWB2ow7WG7r3Q1LQGN4U83BIrkLDaXLjGYvYiYzWbee628fdIwdUze0Mv4eZc+O3ourYWznTxFRA\
TGzhTWUhh4rUJ6nAq6wyf36nF2lK4WnDNFDZ6jraXLHlVo0TIJxCXy+sd5xccPfkVYADDOZXimxZ6tAA\
AAABJRU5ErkJggg=="
button_image = ImageTk.PhotoImage(data=base64.b64decode(IMAGE)) # desencodifica a imagem
ok_button = Button(top, text="ok",image=button_image,compound=LEFT)
ok_button.grid()
top.mainloop()

É importante notar que no PIL é necessário desencodificar a imagem de volta porque essa biblioteca recebe o próprio conteúdo binário da imagem, enquanto que no próprio PhotoImage do Tkinter isso não é necessário.

Página anterior     Próxima página

Páginas do artigo
   1. Quem é o Tkinter
   2. Criando uma aplicação básica
   3. Organização de uma aplicação real e conclusão
Outros artigos deste autor
Nenhum artigo encontrado.
Leitura recomendada

ISO8583py - Utilizando Python para o tratamento de mensagens ISO8583

Interagindo com servidores HTTP com Python

Python - Usando requests anônimos através da rede Tor

Python: automatizando a extração de informações na web com expressões regulares

paramiko - Python + SSH

  
Comentários
[1] Comentário enviado por fabio em 26/12/2014 - 14:54h

Artigo muito bem escrito! Me deu saudades agora do bom e velho Tcl/Tk. Programei muito com ele na década de 90... Putz, tô ficando velho!


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts