You are on page 1of 33

Python

Tkinter
Mdulo de Interface Grfica(GUI) com os Usurios em
Python
Antonio Srio !oueira
Presidente Prudente
"##$
1
Python
Sumrio
%&Introdu'(o&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&)
"&A *lasse Tk&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&+
2
Python
1. Introduo
O Tkinter um conjunto de widgets (componentes de interface grfica) para
Interface Grfica com o Usurio(GUI) Uma das !antagens desse m"du#o grfico $ue
e#e j !em junto com o Python %este m"du#o encontraremos widgets(componentes como
&ot'o( cai)a de te)to)( e!ent hand#ers(manipu#adores de e!entos*rotinas para responder
a e!entos e e!entos s'o* a&rir e fechar jane#a( c#icar um mouse) para $ue uma fun+'o
de fechar uma jane#a( por e)emp#o( seja e)ecutada necessrio fa,er um &inding(uma
atri&ui+'o) do &ot'o para a rotina( e)istem tam&m e!ents #oop $uando a rotina fica
esperando a entrada de dados
-eja este caso acima* o mouse ficou parado em cima do menu .i#e e o manipu#ador de
e!ento automaticamente modificou este &ot'o destacando/o -eja $ue para este caso n'o
foi necessrio fa,er um &inding( uma !e, $ue este tipo de &inding j automtico
0omo todo &om manua# nosso primeiro programa o 12#o 3undo45
6 .i#e* a#o7py
from Tkinter import 8 6 importa o modu#o Tkinter
rai, 9 Tk() 6 cria uma jane#a de mais a#to n:!e# chamada de rai, (root)
w 9 ;a&e#(rai,( te)t9<2#o 3undo4<) 6 insere widgets na jane#a
wpack() 6 mtodo $ue fa, o te)to ca&er na jane#a
rai,main#oop() 6 mostra a jane#a rai, e e)ecuta o e!ent #oop aguardando $ue
6a#gum en!ento aconte+a ou $ue a jane#a seja fechada atra!s de
um 6e!ento destruidor
=)ecute este programa no prompt do sistema atra!s do comando* python a#omundopy
2o e)ecutar um programa em I>;= este poder entrar em conf#ito com o main#oop da
I>;= uma !e, $ue esta interface GUI uma ap#ica+'o Tkinter
3
Python
2. A classe Tk
2.1 Item Bsico: Para tra&a#harmos com a c#asse tk de!emos primeiro disponi&i#i,/#a
atra!s do comando import( depois importar a c#asse tk $ue cria a jane#a principa# com os
widgets minimi,ar( ma)imi,ar e fechar a jane#a( $ue ser !isua#i,ada com o e!ent #oop
main#oop
2.2 Um programa bem simples
???from Tkinter import 8
???rai,9Tk()
???rai,main#oop()
=ste um programa muito simp#es( inc#usi!e os comandos podem ser digitados no I>;=(
e)p#icando no!amente estes comandos* a 7a#inha !oc@ importa o m"du#o Tkinter( na
Aa#inha !oc@ cria a jane#a de n:!e# mais a#to chamada rai,(cria uma instBncia da c#asse
Tkintertk) ou principa# como chamada em outras #inguagens !isuais e a Ca#inha !oc@
manda e)ecutar a jane#a $ue fica em #oop aguardando um e!ento($uando um e!ent
hand#er acontece uma rotina e)ecutada sen'o o sistema fica em #oop)( note $ue est
jane#a j !em com os widgets minini,ar(ma)imi,ar e fechar
2.3 osso primeiro ob!eto "UI: sempre $ue tra&a#hamos com o Tkinter de!emos
importar todo conteDdo do m"du#o( $uando fa,emos isto importamos a c#asse Tk $ue tem
todos o widgets %ossa interface de!e ser estruturada em forma de c#asses a partir da
c#asse rai,( uma instBncia da c#asse Tk Para programarmos com interfaces GUI Tkinter
de!emos citar tr@s conceitos*
2 cria+'o de um o&jeto GUI e a associa+'o a rai,
O mtodo pack
O conceito containers !ersus widgets
E importante di!idirmos os componentes grficos(anteriormente chamados apenas de
widgets) em containers e #idgets. Os widgets ser'o os componentes grficos
4
Python
!is:!eis(gera#mente) da GUI e tem uma fun+'o !o#tada ao usurio( j os containers s'o
componentes $ue agregam !rios widgets( ou seja um recipiente onde co#ocamos os
widgets O Tkinter oferece !rios tipos de containers 10an!as5 um container para
ap#ica+Fes de desenho( e o container mais fre$Gentemente uti#i,ado o 1.rame5 .rames
s'o oferecidos pe#o Tkinter como uma c#asse chamada 1.rame5
-ejamos isto*
from Tkinter import 8
root 9 Tk()
container7 9 .rame(root)
container7pack()
rootmain#oop()
%o programa acima importamos o m"du#o Tk criamos um o&jeto rai, instBncia de Tk e
dentro deste o&jeto co#ocamos um o&jeto container do tipo .rame( este tipo de estrutura
gera uma re#a+'o de pai e fi#ho ou mestre/escra!o de ta# forma $ue ao fecharmos a
instBncia pai ou mestre automaticamente fecharemos a jane#a O o&jeto container7 uma
instBncia de .rame e esta conectado #ogicamente ao o&jeto rai,( uma instBncia de Tk %a
pr")ima #inha temos um mtodo simp#esmente designado( 1pack5 um mtodo $ue
transforma em !isuais as re#a+Fes entre os componentes GUI e seus mestres He !oc@
n'o definir o componente pack ou outro gerenciador de geometria( nunca !er a GUI Um
gerenciador de geometria essencia#mente um 2PI I um meio de di,er ao Tkinter como
!oc@ $uer $ue containers e widgets se apresentem !isua#mente Tkinter oferece tr@s
gerenciadores para esta fina#idade* pack( grid e p#ace Pack e grid s'o os mais usados por
serem mais simp#es Todos os e)emp#os em 1Pensando em Tkinter5 usam pack como
gerenciador de geometria
0omparando dois e)emp#os* %o programa anterior( por n'o termos co#ocado nada dentro
de#a( a rai, mostrou a si mesma na te#a com seu tamanho padr'o( mas neste programa(
n"s preenchemos sua ca!idade com o container7 2gora( a rai, se estica para acomodar
o tamanho de container7( mas como n'o co#ocamos nenhum widget neste frame( nem
especificamos um tamanho m:nimo para e#e( a ca!idade da root se enco#he at o #imite(
podemos di,er $ue esta frame e#stica Por isso n'o h nada para ser !isto a&ai)o da
&arra de t:tu#o desse programa
=)emp#o anterior*
5
Python
=)emp#o atua#*
2.$ %ontainers e #idgets: a estrutura de containers pode ser &astante sofisticada e pode
conter um dentro do outro e dentro destes os widgets
-eja a estrutura acima onde temos a jane#a rai, dentro de#a os o&jetos containers frame 2
e frame J e dentro destas jane#as os widgets Temos agora $ue usar um gerenciador de
geometria para posicionar widgets dentro das jane#as
Para e)emp#ificar criaremos uma jane#a rai, com um container e dentro de#e um widget do
tipo &ot'o
6
Python
from Tkinter import 8
root 9 Tk()
0ontainer7 9 .rame(root)
0ontainer7pack()
&otao 9 Jutton(0ontainer7) 666 (7) cria o&jeto &ot'o
&otaoK<te)t<L9 <2;O 3U%>O4< 666 (A) define o te)to $ue aparece ne#e
&otaoK<&ackground<L 9 <gray< 666 (C) define a cor do &ot'o
&otaopack() 666 (M)
rootmain#oop()
-amos co#ocar mais um &ot'o
from Tkinter import 8
root 9 Tk()
0ontainer7 9 .rame(root)
0ontainer7pack()
&otao 9 Jutton(0ontainer7) 666 (7) cria o&jeto &ot'o
&otaoK<te)t<L9 <2;O 3U%>O4< 666 (A) define o te)to $ue aparece ne#e
&otaoK<&ackground<L 9 <gray< 666 (C) define a cor do &ot'o
&otaopack() 666 (M)
&otao7 9 Jutton(0ontainer7) 666 (7) cria o&jeto &ot'o
&otao7K<te)t<L9 <2;O 3U%>O4< 666 (A) define o te)to $ue aparece ne#e
&otao7K<&ackground<L 9 <&#ue< 666 (C) define a cor do &ot'o
&otao7pack() 666 (M)
rootmain#oop()
7
Python
2.& Usando classes para estruturar o programa: ao escre!er grandes programas
uma &oa idia di!idir os c"digos em c#asses =sta estrutura+'o em c#asses muito
importante e !ai ajud/#o a contro#ar me#hor seu desen!o#!imento Um programa
estruturado em c#asses pro!a!e#mente I especia#mente se seu programa for muito
grande I muito mais fci# de ser entendido Uma considera+'o muito importante $ue
estruturar sua ap#ica+'o como uma c#asse ajudar !oc@ a e!itar o uso de !ari!eis
g#o&ais =!entua#mente( conforme seu programa for crescendo( !oc@ pro!a!e#mente ir
$uerer $ue a#guns de seus e!ent hand#er consigam comparti#har informa+Fes entre si
Uma maneira usar !ari!eis g#o&ais( mas uma tcnica muito ma+ante Um caminho
muito me#hor usar instBncias (isto ( usar 1se#f5 nas !ari!eis)( e para isso !oc@ precisa
estruturar sua ap#ica+'o como c#asses
Para estruturar o programa em c#asses( e)emp#o anterior)( primeiro criamos uma c#asse
chamada 2p#ic e depois transcre!eremos a#guns dos c"digos do programas anteriores
para dentro do seu mtodo construtor (NNinitNN) %esta !ers'o ent'o teremos uma c#asse
chamada 2p#ic (7)(ap#ica+'o) e ne#e definiremos a forma da interface GUI Todo esse
c"digo inserido dentro do mtodo construtor (7a)dessa c#asse Ouando o programa
e)ecutado( uma instBncia da c#asse criada atra!s do(A) comando aplic'Aplic(rai)*(
!eja $ue a instBncia tem a #etra inicia# do nome minDscu#o e a c#asse maiDscu#a
(con!en+'o) e perce&a $ue passamos para esta c#asse como argumento a 1rai,5
from Tkinter import 8
c#ass 2p#ic* 666 (7)
def NNinitNN(se#f( pai)* 666 (7a)
se#f0ontainer7 9 .rame(pai)
se#f0ontainer7pack()
se#f&otao 79 Jutton(se#f0ontainer7)
se#f&otao7K<te)t<L9 <Pe##o( Qor#d4< 6 as informa+Fes s'o guardadas como
6dicionrio nos widgets
se#f&otao7K<&ackground<L 9 <green<
6se#f&otao7 9 Jutton(se#f0ontainer( te)t9RO#a 3undo4R( &ackground9RgreenR)
se#f&otao7pack()
rai, 9 Tk()
ap#ic 9 2p#ic(rai,) 666 (A)
rai,main#oop()
Outro e)emp#o*
from Tkinter import 8
c#ass 2pp#ication(.rame)*
def NNinitNN(se#f( master9%one)*
8
Python
.rameNNinitNN(se#f( master)
se#fmsg 9 ;a&e#(se#f( te)t9<Pe##o Qor#d<) 6 r"tu#o
se#fmsgpack ()
se#f&ye 9 Jutton (se#f( te)t9<Jye<( command9se#f$uit) 6 comando de sa:da
se#f&yepack ()
se#fpack()
app 9 2pp#ication()
main#oop()
Os widgets tem outras configura+Fes como*
height I a#tura do &ot'o em nDmero de #inhas de te)to
width I #argura de &ot'o em nDmero de caracteres de te)to
font I configurar a fonte de te)to
fg I foreground
&g / &ackground
Outro e)emp#o com &ot'o e suas configura+Fes*
from Tkinter import 8
c#ass Sane#a*
def NNinitNN(se#f(top#e!e#)*
se#ffr7 9 .rame(top#e!e#)
se#ffr7pack()
se#f&otao7 9 Jutton(se#ffr7(te)t9ROi4R)
se#f&otao7KR&gRL9RgreenR
se#f&otao7KRfontRL9(R-erdanaR(R7AR(Rita#icR(R&o#dR)
se#f&otao7KRheightRL9C
se#f&otao7pack()
se#f&otaoA 9 Jutton(se#ffr7(&g9RredR( font9(RTimesR(R7TR))
se#f&otaoAKRte)tRL9RTchau4R
se#f&otaoAKRfgRL9Rye##owR
se#f&otaoAKRwidthRL97A
se#f&otaoApack()
rai,9Tk()
Sane#a(rai,)
rai,main#oop()
2.&.1 %lasses do Tkinter:
9
Python
Jutton
Jot'o simp#es/ usado para e)ecutar um comando ou outra opera+'o
0an!as Grficos estruturados Pode ser usado para p#otar e desenhar grficos(
criar editores grficos e para imp#ementar widgets customi,ados
0heck&utton Uepresenta uma !ari!e# $ue pode ter dois !a#ores distintos 0#icando no
&ot'o o !a#or trocado
=ntry Um campo para entrada de te)to
.rame Um widget tipo container 2 .rame pode ter &orda e fundo e usado
para agrupar widgets $uando criamos uma ap#ica+'o ou di#ogo
;a&e# 3ostra um te)to ou imagem
;ist&o) 3ostra uma #ista de a#ternati!as 2 #ist&o) pode ser configurada para
comportar/se como radio&utton ou check#ist
3enu Um paine# de menu Usado para imp#ementar menus pu##down e popup
3enuJutton Um &ot'o de menu Usado para imp#ementar menus pu##down
3essage 3ostra um te)to Himi#ar ao #a&e#( mas podemos automaticamente
ajustar te)to ao tamanho e propor+'o
Uadio&utton Uepresenta um !a#or de !ari!e# $ue pode ter !rios !a#ores 0#icando o
&ot'o( o !a#or da !ari!e# posicionado para a$ue#e !a#or e os outros
!a#ores s'o apagados
Hca#e Permite posicionar um !a#or numrico arrastando um ponteiro
Hcro##&ar Jarra de ro#amento padr'o usada com widgets can!as(entry(#ist&o) e
te)t
Te)t .ormata um te)to Permite a !oc@ mostrar e editar te)tos com !rios
esti#os e atri&utos Tam&m suporta incorporar imagens e jane#as
Top#e!e# Sane#a de mais a#to n:!e#
Todos os widgtes tem a mesma hierar$uia
Um widgtes t:pico possue cerca de 7VW mtodos 2 c#asse Top#e!e# fornece o gerenciador
de interfaces 2#m disso temos os gestores de geometria $ue permite criar #ayouts( s'o
e#es*Grid (#ayouts em uma grade &i/dimensiona#)( Pack(#aytouts em &#ocos retangu#ares) e
P#ace(>efine o #oca# $ue co#ocaremos o widget)
2.+ ,osicionando os bot-es: j !erificamos $ue o mtodo pack $ue cuida da parte
!isua# do widget e e#e possue um argumento chamado side $ue pode assumir os !a#ores*
#eft( right(top(&ottom
6 .i#e* he##oApy
from Tkinter import 8
c#ass 2pp*
10
Python
def NNinitNN(se#f( master)*
frame 9 .rame(master)
framepack()
se#f&utton 9 Jutton(frame( te)t9<OUIT<( fg9<red<( command9frame$uit) 667
se#f&uttonpack(side9;=.T)
se#fhiNthere 9 Jutton(frame( te)t9<Pe##o<( command9se#fsayNhi) 66A
se#fhiNtherepack(side9;=.T)
def sayNhi(se#f)*
print <hi there( e!eryone4<
root 9 Tk()
app 9 2pp(root)
rootmain#oop()
O&ser!e em 7 e A do programa acima os comandos $ue foram associados aos &otFes

from Tkinter import 8
c#ass Packing*
def NNinitNN(se#f(instanciaNTk)*
se#fcontainer79.rame(instanciaNTk)
se#fcontainerA9.rame(instanciaNTk)
se#fcontainerC9.rame(instanciaNTk)
se#fcontainer7pack()
se#fcontainerApack()
se#fcontainerCpack()
Jutton(se#fcontainer7(te)t9RJ7R)pack()
Jutton(se#fcontainerA(te)t9RJAR)pack(side9;=.T)
Jutton(se#fcontainerA(te)t9RJCR)pack(side9;=.T)
se#f&M9Jutton(se#fcontainerC(te)t9RJMR)
se#f&V9Jutton(se#fcontainerC(te)t9RJVR)
se#f&T9Jutton(se#fcontainerC(te)t9RJTR)
se#f&Tpack(side9UIGPT)
se#f&Mpack(side9UIGPT)
se#f&Vpack(side9UIGPT)
rai,9Tk()
Packing(rai,)
11
Python
rai,main#oop()
-eja nesta figura $ue ap"s co#ocarmos um &ot'o no container(ca!idade)( a ca!idade
preenchida pe#o &ot'o e dei)a a rea restante para os pr")imos widgets( $uando n'o
co#ocamos o parBmetro side o &ot'o co#ocado no topo do container dei)ando a rea
#ogo a&ai)o para !oc@ co#ocar os outros widgets %'o de!emos dar !rios
posicionamentos ao widget numa frame uma !e, $ue isto pode causar efeitos indesejados
$uando a#terarmos o tamanho de#a %o e)emp#o acima co#ocamos tr@s containers
posicionados em top (argumento defau#t)
= depois co#ocamos ne#es o &otFes( criando a jane#a mostrada
12
Python
2.. /anipulando os e0entos (e0ent 1andler*: agora iremos deta#har como !oc@ pode
associar um e0ent 1andler a um e0ent como c#icar um &ot'o Os e!ents hand#ers s'o
a+Fes e)ecutadas em resposta a um e!ent( para $ue isso ocorra precisamos associar
este e!ento ao e!ent hand#er atra!s de mtodo chamado e!ent &inding cuja sinta)e
widget&ind(en!ent( e!ent hand#er) Outra forma de #igar um manipu#ador de e!entos a um
widget chamado 1command &inding5 e n"s a !eremos em a#guns programas da$ui pra
frente Por ora( !ejamos me#hor o e!ent &inding( e tendo entendido este( ser mo#e,a
e)p#icar o command &inding 2ntes de come+armos( !amos esc#arecer uma coisa* a
pa#a!ra 1&ot'o5 pode ser usada para designar duas coisas inteiramente diferentes*
/ um widget( Jutton I uma GUI $ue mostrada no monitor do computador e
/ um &ot'o no seu mouse I a$ue#e $ue !oc@ pressiona com o dedo
from Tkinter import 8
c#ass Sane#a*
def NNinitNN(se#f(top#e!e#)*
se#fframe9.rame(top#e!e#)
se#fframepack()
se#fte)to9;a&e#(se#fframe( te)t9R0#i$ue para ficar amare#oR) 6667
se#fte)toKRwidthRL9AT
se#fte)toKRheightRL9C
se#fte)topack()
se#f&otao!erde9Jutton(se#fframe(te)t9R0#i$ueR)
se#f&otao!erdeKR&ackgroundRL9RgreenR
se#f&otao!erde&ind(<XJutton/7?<(se#fmudaNcor) 666A
se#f&otao!erdepack()
def mudaNcor(se#f( e!ent)* 66C
6 3uda a cor do &otao4
if se#f&otao!erdeKR&gRL99RgreenR*
se#f&otao!erdeKR&gRL9Rye##owR
se#fte)toKRte)tRL9R0#i$ue para ficar !erdeR
e#se*
se#f&otao!erdeKR&gRL9RgreenR
se#fte)toKRte)tRL9R0#i$ue para ficar amare#oR
rai,9Tk()
Sane#a(rai,)
rai,main#oop()
13
Python
%o programa acima inserimos outro widget do tipo 2abel (7) $ue ser!e para co#ocarmos
r"tu#os ou me#hor te)tos na jane#a -erifi$ue $ue $uando criamos widget e#e est
associado a um jane#a pai ou container pai( $ue o #oca# onde e#e ser encai)ado
2inda no programa acima temos a associa+'o do e!ento apertar o &ot'o 7 do mouse com
a e)ecu+'o da fun+'o mudar de cor (A)( !eja nesta #inha (se#f&otao!erde&ind(<XJutton/
7?<(se#fmudaNcor)) $ue temos a string 1XJutton/7?5 $ue passada como argumento $ue
representa apertar o &ot'o 7 do mouse( por e)emp#o se fosse apertar o &ot'o enter a
string seria 1XUeturn?5
2...1 30entos do /ouse 4 -imos no e)emp#o acima $ue ao acionarmos o &ot'o 7 do
mouse o &ot'o muda de cor( podemos tam&m !erificar no e)emp#o acima $ue na #inha
com o r"tu#o C na passagem de parBmetro temos um o&jeto e!ento sendo passado como
argumento( em Tkinter sempre $ue um e!ento ocorre um o&jeto passado contendo
todas as informa+Fes necessrias do e!ento Um ob!eto e0ento um tipo especia# de
o&jeto contendo todas as informa+Fes necessrias a manipu#a+'o do e!ento Ouando
$uisermos passar uma se$u@ncia de tec#as $ue de!e ser acionadas( isto poss:!e#
atra!s de uma tup#a !eja e)emp#o*
from Tkinter import 8
c#ass Sane#a*
def NNinitNN(se#f(top#e!e#)*
se#fframe9.rame(top#e!e#)
se#fframepack()
se#fte)to9;a&e#(se#fframe( te)t9R0#i$ue para ficar amare#oR) 6667
se#fte)toKRwidthRL9AT
se#fte)toKRheightRL9C
se#fte)topack()
se#f&otao!erde9Jutton(se#fframe(te)t9R0#i$ueR)
se#f&otao!erdeKR&ackgroundRL9RgreenR
se#f&otao!erde&ind((<XJutton/7?<(5XJutton/C?5)(se#fmudaNcor) 666A
se#f&otao!erdepack()
def mudaNcor(se#f( e!ent)* 66C
6 3uda a cor do &otao4
if se#f&otao!erdeKR&gRL99RgreenR*
se#f&otao!erdeKR&gRL9Rye##owR
se#fte)toKRte)tRL9R0#i$ue para ficar !erdeR
e#se*
se#f&otao!erdeKR&gRL9RgreenR
se#fte)toKRte)tRL9R0#i$ue para ficar amare#oR
rai,9Tk()
14
Python
Sane#a(rai,)
rai,main#oop()
=)perimente ainda as strings 1X3otion?5 (mo!imenta+'o do mouse)( 1X;ea!e?5(sai do
&ot'o) e 1XJuttonUe#ase/Y?5 (&ot'o do meio e Y pode ser 7( A ou C)
2...2 5oco e e0entos do teclado I o foco um mecanismo $ue ser!e para indicar $ue
e#emento grfico (widget) est respondendo aos e!entos Um mtodo importante $uando
fa#amos em foco o mtodo widg7focusNforce() $ue co#oca o foco no widget #idg1. %a
ta&e#a a&ai)o !emos as strings associadas aos e!entos $uando desen!o#!emos um
programa
Tabela de 30entos
30ento 6tring
2pertar tec#a =nter 1XUeturn?5
2pertar tec#a >e#ete 1X>e#ete?5
2pertar tec#a Jackspace 1XJackHpace?5
2pertar tec#a =scape 1X=scape?5
2pertar Heta para =s$uerda 1X;eft?5
2pertar Heta para >ireita 1XUight?5
2pertar Heta para Jai)o 1X>own?5
2pertar Heta para 0ima 1XUp?5
Tirar o foco do widget 1X.ocusOut?5
0o#ocar o foco no widget 1X.ocusIn?5
2pertando $ua#$uer tec#a a#fanumrica 1XZeyPress/2#fa?5 ou 1X2#fa?5
Ho#tando tec#a 2#fa 1XZeyUe#ease/2#fa?5
2pertando duas !e,es &ot'o 7 mouse 1X>ou&#eJutton/7?5
2pertando C !e,es tec#a P 1XTrip#e/ZeyPress/P?5
2pertando $ua#$uer &ot'o mouse 1X2ny/Jutton?5
2pertando $ua#$uer tec#a 1X2ny/ZeyPress2?5
=)emp#o e!entos*
6 /8/ coding* cp7AVA /8/ 6 usar caracteres acentuados
from Tkinter import 8
c#ass Sane#a*
def NNinitNN(se#f(top#e!e#)*
se#fframe9.rame(top#e!e#)
se#fframepack()
se#fframeA9.rame(top#e!e#)
se#fframeApack()
15
Python
se#ftitu#o9;a&e#(se#fframe(te)t9R.O0OR(
font9(R-erdanaR(R7CR(R&o#dR))
se#ftitu#opack()
se#fmsg9;a&e#(se#fframe(width9MW(height9T(
te)t 9 R2P=UT= T2J P2U2 20IO%2U .O0O4R)
se#fmsgfocusNforce()
se#fmsgpack()

6 >efinindo o &ot'o 7
se#f&W79Jutton(se#fframeA(te)t9RJot'o 7R)
se#f&W7KR&gRL9Rsky&#ueR
se#f&W7&ind(<XUeturn?<(se#fkeypressW7)
se#f&W7&ind(<X2ny/Jutton?<(se#f&uttonW7)
se#f&W7&ind(<X.ocusIn?<(se#ffinW7)
se#f&W7&ind(<X.ocusOut?<(se#ffoutW7)
se#f&W7KRre#iefRL9UI>G=
se#f&W7pack(side9;=.T)
6 >efinindo o &ot'o A
se#f&WA9Jutton(se#fframeA(te)t9RJot'o AR)
se#f&WAKR&gRL9Rsky&#ueR
se#f&WA&ind(<XUeturn?<(se#fkeypressWA)
se#f&WA&ind(<X2ny/Jutton?<(se#f&uttonWA)
se#f&WA&ind(<X.ocusIn?<(se#ffinWA)
se#f&WA&ind(<X.ocusOut?<(se#ffoutWA)
se#f&WAKRre#iefRL9UI>G=
se#f&WApack(side9;=.T)
def keypressW7(se#f(e!ent)*
se#fmsgKRte)tRL9R=%T=U so&re o Jot'o 7R

def keypressWA(se#f(e!ent)*
se#fmsgKRte)tRL9R=%T=U so&re o Jot'o AR

def &uttonW7(se#f(e!ent)*
se#fmsgKRte)tRL9R0#i$ue so&re o Jot'o 7R

def &uttonWA(se#f(e!ent)*
se#fmsgKRte)tRL9R0#i$ue so&re o Jot'o AR


def finW7(se#f(e!ent)*
se#f&W7KRre#iefRL9HU%Z=%

def foutW7(se#f(e!ent)*
se#f&W7KRre#iefRL9U2IH=>

def finWA(se#f(e!ent)*
16
Python
se#f&WAKRre#iefRL9HU%Z=%
pass
def foutWA(se#f(e!ent)*
se#f&WAKRre#iefRL9U2IH=>
pass
rai,9Tk()
Sane#a(rai,)
rai,main#oop()
Outro e)emp#o( de associa+'o de e!entos*
from Tkinter import 8
c#ass Sane#a*
def NNinitNN(se#f(top#e!e#)*
se#fframe9.rame(top#e!e#)
se#fframepack()
se#f&79Jutton(se#fframe)
se#f&7&ind(<XJutton/7?<( se#fpressN&7) 6aperta &otao mouse
se#f&7&ind(<XJuttonUe#ease?<( se#fre#easeN&7) 6desaperta &otao mouse
se#f&7KRte)tRL 9 R0#i$ue a$ui4R
se#f&7KRwidthRL( se#f&7KR&gRL 9 AW( RpinkR
se#f&7KRfgRL9Rye##owR
se#f&7pack(side9;=.T)
se#f&A9Jutton(se#fframe)
se#f&AKRwidthRL( se#f&AKR&gRL 9 AW( RpinkR
se#f&AKRfgRL9Rye##owR
se#f&Apack(side9;=.T)
se#f&C9Jutton(se#fframe( command9se#fc#ickN&C) 63ouse e!ento comp#eto
se#f&CKRwidthRL( se#f&CKR&gRL 9 AW( RpinkR
se#f&CKRfgRL9Rye##owR
se#f&Cpack(side9;=.T)
def pressN&7(se#f(e!ent)*
se#f&7KRte)tRL9RR
se#f&AKRte)tRL9R=stou a$ui4R
def re#easeN&7(se#f(e!ent)*
se#f&AKRte)tRL9RR
se#f&CKRte)tRL9R3udei de no!o4R
def c#ickN&C(se#f)*
se#f&CKRte)tRL9R-oc@ me pegouR
rai,9Tk()
Sane#a(rai,)
rai,main#oop()
2.7 Usando %1eckButton: este tipo de widget usado $uando $ueremos fa,er esco#ha
entre !a#ores distintos
Para usar um 0heck&utton( cria/se uma !ari!e# Tkinter*
!ar 9 Int-ar()
17
Python
c 9 0heck&utton(master( te)t9<=)pand<( !aria&#e9!ar)
0omo padr'o esta !ari!e# posicionada em 7 $uando o &ot'o se#ecionado e W $uando
n'o -oc@ pode mudar estes !a#ores usando as op+Fes on!a#ue e off!a#ue =sta !ari!e#
n'o precisa ser um nDmero inteiro
!ar 9 Htring-ar()
c 9 0heck&utton(
master( te)t9<0o#or image<( !aria&#e9!ar(
on!a#ue9<UGJ<( off!a#ue9<;<
)
=)emp#o*
from Tkinter import 8
c#ass &otaoesco#ha*
def NNinitNN(se#f( master)*
se#fframe9.rame(master(width9VWW(height97WW)
mastertit#e(<0heck Jutton<)
se#fframepack()
se#f!ar 9 Int-ar()
c 9 0heck&utton(master( te)t9<=sco#ha<(
!aria&#e9se#f!ar)
c&ind(<X7?<(se#fc&)
cpack()

def c&(se#f(e!ent)*
print se#f!ar
if se#f!ar997*
print <des#igado<
se#f!ar9W
e#se*
print <#igado<
se#f!ar97
rai,9Tk()
&otaoesco#ha(rai,)
rai,main#oop()
18
Python
2.8 %riando /enus: para criar um menu !oc@ de!e instanciar a c#asse 3enu e usar o
mtodo add para adicionar entradas
[ add9command(label'string: command'callback* / adiciona uma entrada ao menu
[ add9separator(* / adiciona um separador de #inha Usado para agrupar entradas
[ add9cascade(label'string: menu'menu instance* / adiciona um su&menu
6 .i#e* tkintermenu7py
from Tkinter import 8
def ca##&ack()*
print <0hamada de retorno<
root 9 Tk()
6 create a menu
menu 9 3enu(root)
rootconfig(menu9menu)
fi#emenu 9 3enu(menu)
menuaddNcascade(#a&e#9<2r$ui!o<( menu9fi#emenu)
fi#emenuaddNcommand(#a&e#9<%o!o<( command9ca##&ack)
fi#emenuaddNcommand(#a&e#9<2&rir<( command9ca##&ack)
fi#emenuaddNseparator()
fi#emenuaddNcommand(#a&e#9<Hair<( command9ca##&ack)
he#pmenu 9 3enu(menu)
menuaddNcascade(#a&e#9<2juda<( menu9he#pmenu)
he#pmenuaddNcommand(#a&e#9<Ho&re<( command9ca##&ack)
main#oop()
19
Python
2.1; Barra de <erramentas: -rios programas co#ocam a&ai)o da &arra de menu uma
&arra de ferramentas( norma#mente esta &arra contm !rios &otFes como a&rir ar$ui!o(
imprimir( etc
=)emp#o de &arra de ferramentas* uma frame com !rios &otFes
6ar$ui!o Tkintertoo#&arpy
from Tkinter import 8
root 9 Tk()
def ca##&ack()*
print <0hamada de retorno<
6 create a menu
menu 9 3enu(root)
rootconfig(menu9menu)
fi#emenu 9 3enu(menu)
menuaddNcascade(#a&e#9<2r$ui!o<( menu9fi#emenu)
fi#emenuaddNcommand(#a&e#9<%o!o<( command9ca##&ack)
fi#emenuaddNcommand(#a&e#9<2&rir<( command9ca##&ack)
fi#emenuaddNseparator()
fi#emenuaddNcommand(#a&e#9<Hair<( command9ca##&ack)
he#pmenu 9 3enu(menu)
menuaddNcascade(#a&e#9<2juda<( menu9he#pmenu)
he#pmenuaddNcommand(#a&e#9<Ho&re<( command9ca##&ack)
6 criar &arra de ferramentas
too#&ar 9 .rame(root)
& 9 Jutton(too#&ar( te)t9<no!o<( width9T( command9ca##&ack)
&pack(side9;=.T( pad)9A( pady9A)
& 9 Jutton(too#&ar( te)t9<a&re<( width9T( command9ca##&ack)
&pack(side9;=.T( pad)9A( pady9A)
too#&arpack(side9TOP( fi##9Y)
20
Python
2.11 Barra de 6tatus: !ejamos como gerar uma &arra de status
6 .i#e* tkHtatusJarApy
from Tkinter import 8
c#ass HtatusJar(.rame)*
def NNinitNN(se#f(master)*
.rameNNinitNN(se#f(master)
se#f#a&e#9;a&e#(se#fmaster(&d97(&g9<&#ack<(re#ief9HU%Z=%(anchor9Q(te)t9RR)
se#f#a&e#pack()
def set(se#f(format)*
se#f#a&e#config(te)t9format)
se#f#a&e#updateNid#etasks()
def c#ear(se#f)*
se#f#a&e#config(te)t9<<)
se#f#a&e#updateNid#etasks()
c#ass te#a*
def NNinitNN(se#f(master)*
se#f)9<<
se#fpai 9 master
se#f0ontainer7 9 .rame(master)
se#f0ontainer7pack()
se#f&utton7 9 Jutton(se#f0ontainer7(command9se#f&utton70#ick(te)t9<2perte<)
se#f&utton7pack(side9TOP)
se#fstatus9HtatusJar(se#f0ontainer7)
se#f&uttonA 9Jutton(se#f0ontainer7(command9se#f&uttonA0#ick(te)t9<2pague<)
se#f&uttonApack(side9UIGPT)


def &utton70#ick(se#f)*
se#f)9se#f)\< <
se#fstatusset(se#f))
def &uttonA0#ick(se#f)*
se#fstatusc#ear()

Uai,9Tk()
rai,9te#a(Uai,)
Uai,main#oop()
21
Python
3odifi$ue o programa para os &otFes ficarem ordenados
2.12 %riar uma !anela de entrada de dados: este e)emp#o cria um widget jane#a de a#to
n:!e# e adiciona a#guns widgets para e#e 2 rotina $ue chamou ent'o usa waitNwindow
para esperar o di#ogo ser fechado O usurio c#ica em OZ e o !a#or do campo impresso
e o di#ogo e)p#icitamente encerrado

6 .i#e* tkentradadedados7py
from Tkinter import 8
c#ass 3y>ia#og*
def NNinitNN(se#f( parent)*
top 9 se#ftop 9 Top#e!e#(parent)
;a&e#(top( te)t9<-a#or<)pack()
se#fe 9 =ntry(top)
se#fepack(pad)9V)
& 9 Jutton(top( te)t9<OZ<( command9se#fok)
&pack(pady9V)
def ok(se#f)*
print <!a#or igua# a <( se#feget()
se#ftopdestroy()
root 9 Tk()
Jutton(root( te)t9<Oi4<)pack()
rootupdate()
d 9 3y>ia#og(root)
rootwaitNwindow(dtop)
O widget 3ntr= uma forma de entrada de dados Os dados informados pe#o usurio
neste campo est'o na forma de strings( como a fun+'o rawNinput 2tra!s do mtodo get(
fornecido pe#o 3ntr= podemos uti#i,ar os dados entrados em nosso c"digo =ste widget
possui as mesmas configura+Fes $ue &otFes e #a&e#s e)ceto a a#tura 1eig1t $ue neste
caso de uma #inha Para entrada de senhas podemos uti#i,ar a op+'o show9R8R $ue
22
Python
mostra asteriscos em !e, dos dados tec#ados
Outro e)emp#o*
6.i#e* entradadedadosCpy
from Tkinter import 8
c#ass entradadedados*
def NNinitNN(se#f(Pai)*
se#fpai9.rame(Pai)
se#fpaipack()
;a&e#(se#fpai(te)t9<%ome<(fg9<&#ack<)grid(row9W)
;a&e#(se#fpai(te)t9<=ndereco<)grid(row97)
se#fe79=ntry(se#fpai)
se#feA9=ntry(se#fpai)
se#fe7grid(row9W( co#umn97)
se#feAgrid(row97(co#umn97)
root9Tk()
Uai,9entradadedados(root)
Uai,paimain#oop()

/ais um e>emplo e neste usamos uma uma op+'o chamada de pad= para dar um
espa+o e)tra entre &ordas e widgets dentro da frame
.igura pady e pad) em um widget tipo &ot'o( aumentando os espa+os entre o te)to e a
&orda
=)emp#o de uso pady e pad)*
se#f&WA9Jutton(se#fframeA(te)t9RJot'o AR)
se#f&WAKRpad)RL(se#f&WAKRpadyRL 9 7W( V
? e>emplo:
23
Python
6 .i#e* tkpassword7py
from Tkinter import 8
c#ass Passwords*
def NNinitNN(se#f(top#e!e#)*
se#fframe79.rame(top#e!e#)
se#fframe7pack()
;a&e#(se#fframe7(te)t9RP2HHQOU>HR( fg9Rdark&#ueR(
font9(R-erdanaR(R7MR(R&o#dR)( height9C)grid(row9W)
fonte79(R-erdanaR(R7WR(R&o#dR)
;a&e#(se#fframe7(te)t9R%ome* R(
font9fonte7(width9])grid(row97(co#umn9W)
se#fnome9=ntry(se#fframe7(width97W(
font9fonte7)
se#fnomefocusNforce() 6 Para o foco come+ar neste campo
se#fnomegrid(row97(co#umn97)
;a&e#(se#fframe7(te)t9RHenha* R(
font9fonte7(width9])grid(row9A(co#umn9W)
se#fsenha9=ntry(se#fframe7(width97W(show9R8R(
font9fonte7)
se#fsenhagrid(row9A(co#umn97)
se#fconfere9Jutton(se#fframe7( font9fonte7( te)t9R0onferirR(
&g9RpinkR( command9se#fconferir(pad)97W(pady97W) 6 retire pad e !eja o &otao
se#fconferegrid(row9C(co#umn9W)
se#fmsg9;a&e#(se#fframe7(font9fonte7(
height9C(te)t9R2GU2U>2%>OR)
se#fmsggrid(row9M(co#umn9W)
def conferir(se#f)*
%O3=9se#fnomeget()
H=%P29se#fsenhaget()
if %O3= 99 H=%P2*
se#fmsgKRte)tRL9R20=HHO P=U3ITI>OR
se#fmsgKRfgRL9RdarkgreenR
e#se*
se#fmsgKRte)tRL9R20=HHO %=G2>OR
se#fmsgKRfgRL9RredR
se#fnomefocusNforce()
instancia9Tk()
Passwords(instancia)
instanciamain#oop()
24
Python
2.13 Usando o con<igure:
from Tkinter import 8
top 9 .rame() ^ toppack()
rotu#o 9 ;a&e# (top( te)t9<U"tu#o =)emp#o<(
foreground9<&#ue<)
rotu#opack ()
rotu#oconfigure(re#ief9<ridge<( font9<2ria# AM &o#d<(
&order9V( &ackground9<ye##ow<)
topmain#oop()
Hem configure*
0om configure*
Outro e)emp#o do configure*
from Tkinter import 8
top 9 .rame() ^ toppack()
a 9 ;a&e# (top( te)t9<2<) ^ apack (side9<#eft<)
& 9 ;a&e# (top( te)t9<J<) ^ &pack (side9<&ottom<)
c 9 ;a&e# (top( te)t9<0<) ^ cpack (side9<right<)
d 9 ;a&e# (top( te)t9<><) ^ dpack (side9<top<)
for widget in (a(&(c(d)*
widgetconfigure(re#ief9<groo!e<( &order97W(
font9<Times AM &o#d<)
topmain#oop()
25
Python
2.1$ Um e>emplo usando a opo <ill:
<ill (@none@: @>@: @=@ ou @bot1@*

Indica como o desenho do e#emento ir preencher o espa+o a#ocado
R)R _ RyR indica $ue ir preencher a #argura _ a#tura
R&othR indica preenchimento de todo o espa+o
RnoneR indica $ue apenas o espa+o necessrio ser ocupado (defau#t)
from Tkinter import 8
top 9 .rame() ^ toppack()
a 9 ;a&e# (top( te)t9<2<) ^ apack (side9<#eft<(
fi##9<y<)
& 9 ;a&e# (top( te)t9<J<) ^ &pack (side9<&ottom<(
fi##9<)<)
c 9 ;a&e# (top( te)t9<0<) ^ cpack (side9<right<)
d 9 ;a&e# (top( te)t9<><) ^ dpack (side9<top<)
for widget in (a(&(c(d)*
widgetconfigure(re#ief9<groo!e<( &order97W(
font9<Times AM &o#d<)
topmain#oop()
2.1$ %an0as: o widget can!as fornece uma faci#idade de estrutura grfica para o Tkinter
=#e a#tamente !ersti# e usado para desenhar e p#otar grficos( criar editor grfico e
criar widgets padroni,ados( at anima+Fes s'o poss:!eis Por defau#t( no!os itens s'o
desenhados acima dos itens $ue j est'o no 0an!as O Tkinter fornece um conjunto de
26
Python
mtodos permitindo a !oc@ manipu#ar os itens de !rias formas e adicionar e!entos e
retorno de#es indi!idua#mente
-oc@ de!e usar o widget 0an!as para mostrar e editar grficos e outros desenhos
e ainda imp#ementar !rios tipos de widgets padroni,ados Por e)emp#o* !oc@ pode usar
um 0an!as como uma &arra de conc#us'o atua#i,ando um o&jeto retBngu#o
O 0an!as suporta os seguintes itens*
arcos I arco de c:rcu#o
&itmap I imagem &inria
imagem I imagem co#orida
#inha I #inha po#igona#
o!a# I c:rcu#os e e#ipses
po#:gonos
retBngu#o
te)to
jane#a I um widget tk
>efine/se um 0an!as da mesma forma $ue um outro widget $ua#$uer( a#m de
possuir as op+Fes de configura+'o de &otFes e #a&e#s( e#e possue as op+Fes bd e cursor
2 op+'o bd especifica a espessura da &orda do widget em pi)e#s e a op+'o cursor define
de $ue forma o cursor aparece $uando est posicionado no widget =)istem muitas
op+Fes de cursor !#idas para $ua#$uer widget -amos ao nosso primeiro e)emp#o
from Tkinter import 8
c#ass Zan!as*
def NNinitNN(se#f(rai,)*
se#fcan!as7 9 0an!as(rai,( width97WW( height9AWW(
cursor9Rf#eurR( &d97W(
&g9RredR)
se#fcan!as7pack(side9;=.T)
se#fcan!asA 9 0an!as(rai,( width97WW( height9AWW(
cursor9RstarR( &d9V(
&g9Rye##owR)
se#fcan!asApack(side9;=.T)
instancia9Tk()
Zan!as(instancia)
instanciamain#oop()
-eja $ue criamos os can!as diretamente na jane#a top/#e!e#
27
Python
6istema de %oordenadas %an0as: O sistema de coordenadas est mostrado em figura
a&ai)o
Ae!a Bue a coordenada ;:; est situada a esBuerda e no alto e o ei>o = est
in0ertido.
3>emplo do comando Bue cria uma lin1a
from Tkinter import 8
c#ass Zan!as*
def NNinitNN(se#f(rai,)*
28
Python
se#fcan!as7 9 0an!as(rai,( width9MWW( height9MWW(
cursor9Rf#eurR( &d97W(
&g9RredR)
se#fcan!as7createN#ine(AWW(AWW(ACW(ACW(7WW(7VW(fi##9R&#ackR)
se#fcan!as7pack()
instancia9Tk()
Zan!as(instancia)
instanciamain#oop()
2 sinta)e do comando para desenhar uma #inha num can!as *
sel<.nome9do9can0as.create9line(>1:=1:....:>n:=n* I a #inha come+a em )7(y7 e segue
a )A(yA e depois )C( yC at )n(yn Podemos definir a op+'o #idt1'nCmero $ue ser!e
para definir espessura da #inha
from Tkinter import 8
c#ass Zan!as*
def NNinitNN(se#f(rai,)*
se#fcan!as7 9 0an!as(rai,( width9MWW( height9MWW(
cursor9Rf#eurR( &d97W(
&g9RredR)
se#fcan!as7createN#ine(AWW(AWW(ACW(ACW(7WW(7VW(fi##9R&#ackR(width9M)
se#fcan!as7pack()
instancia9Tk()
Zan!as(instancia)
instanciamain#oop()
0o#ocando te)to e desenhando c:rcu#os num can!as*
29
Python
6.i#e* can!asMpy
from Tkinter import 8
c#ass Zan!as*
def NNinitNN(se#f(rai,)*
se#fcan!as7 9 0an!as(rai,( width9MWW( height9MWW(
cursor9Rf#eurR( &d97W(
&g9RredR)
)y 9 AW( AW( CWW( 7]W
se#fcan!as7createNarc()y( start9W( e)tent9A`W( fi##9<red<)
se#fcan!as7createNarc()y( start9A`W( e)tent9TW( fi##9<&#ue<)
se#fcan!as7createNarc()y( start9CCW( e)tent9CW( fi##9<green<)
se#fcan!as7createNte)t(AWW(CWW(te)t9<Grabfico<(font9(R2ria#R(RATR(R&o#dR))
se#fcan!as7pack()
se#fframe9.rame(instancia)
se#f#a&e#9;a&e#(te)t9<>esenhando #inhas<)
se#fframepack()
se#f#a&e#pack()
instancia9Tk()
Zan!as(instancia)
instanciamain#oop()
3>emplo com retDngulo e polEgono:
6.i#e* can!asVpy
from Tkinter import 8
30
Python
c#ass Zan!as*
def NNinitNN(se#f(rai,)*
se#fcan!as7 9 0an!as(rai,( width9MWW( height9MWW(
cursor9Rf#eurR( &d97W(
&g9RredR)
)y 9 AW( AW( CWW( 7]W
se#fcan!as7createNarc()y( start9W( e)tent9A`W( fi##9<red<)
se#fcan!as7createNarc()y( start9A`W( e)tent9TW( fi##9<&#ue<)
se#fcan!as7createNarc()y( start9CCW( e)tent9CW( fi##9<green<)
se#fcan!as7createNte)t(AWW(CVW(te)t9<Grabfico<(font9(R2ria#R(RATR(R&o#dR))
se#fcan!as7createNpo#ygon(AWW(AWW(AWW(CWW(CWW(CWW(AWW(AWW( fi##9Rye##owR)
se#fcan!as7createNrectang#e(AWW(7VW(AVW(AWW(fi##9R&#ueR)
se#fcan!as7pack()
se#fframe9.rame(instancia)
se#f#a&e#9;a&e#(te)t9<>esenhando #inhas<)
se#fframepack()
se#f#a&e#pack()
instancia9Tk()
Zan!as(instancia)
instanciamain#oop()
Um e)emp#o mostrando a#guns outros comandos*
6.i#e* tkpa#hetapy
31
Python
from Tkinter import 8
c#ass Pa#heta*
def NNinitNN(se#f(rai,)*
rai,tit#e(<Pa#heta<)
se#fcan!as90an!as(rai,( width9AWW( height9AWW)
se#fcan!aspack()
se#fframe9.rame(rai,)
se#fframepack()
se#fcan!ascreateNo!a#(7V( 7V( 7]V( 7]V(
fi##9RwhiteR( tag9R&o#aR)
;a&e#(se#fframe(te)t9R-erme#ho* R)pack(side9;=.T)
se#f!erme#ho9=ntry(se#fframe( width9M)
se#f!erme#hofocusNforce()
se#f!erme#hopack(side9;=.T)
;a&e#(se#fframe(te)t9R-erde* R)pack(side9;=.T)
se#f!erde9=ntry(se#fframe( width9M)
se#f!erdepack(side9;=.T)
;a&e#(se#fframe(te)t9R2,u#* R)pack(side9;=.T)
se#fa,u#9=ntry(se#fframe( width9M)
se#fa,u#pack(side9;=.T)
Jutton(se#fframe( te)t9R3ostrarR(
command9se#fmisturar)pack(side9;=.T)
se#frg&9;a&e#(se#fframe( te)t9RR( width9](
font9(R-erdanaR(R7WR(R&o#dR))
se#frg&pack()
def misturar(se#f)*
cor9<6cWA)cWA)cWA)< c(int(se#f!erme#hoget())(
int(se#f!erdeget())(
int(se#fa,u#get()))
se#fcan!asde#ete(R&o#aR)
se#fcan!ascreateNo!a#(7V( 7V( 7]V( 7]V(
fi##9cor( tag9R&o#aR)
se#frg&KRte)tRL 9 cor
se#f!erme#hofocusNforce()
inst 9 Tk()
Pa#heta(inst)
instmain#oop()
32
Python
Uefer@ncia Ji&#iogrfica*
.erg Hte!en( Pensando em Tkinter I Tradu+'o Sosu ;a&aki ( Unesp / I#ha Ho#teira / AWWM
;undh .redik( 2n Introduction to Tkinter(7ddd
;a&aki Sosu( Introdu+'o a Python 3"du#o 0 I Tkinter( Unesp I I#ha Ho#teira
33

You might also like