Prévia do material em texto
Roteiro da Aula 03 Exemplo: Conversão de Temperaturas (converteTemperaturas.py) from Tkinter import * def clicouBotaoFC(): f = float(entryF.get()) c = (f - 32) / 1.8 entryC.delete(0, END) entryC.insert(0, "%.1f" % c) def clicouBotaoCF(): c = float(entryC.get()) f = 1.8*c + 32 entryF.delete(0, END) entryF.insert(0, "%.1f" % f) # cria o label Label(text="Graus Fahrenheit:"). \ grid(row=0, column=0, padx=5, pady=5) # cria a caixa de texto entryF = Entry(width=10, justify=RIGHT) entryF.grid(row=0, column=1, padx=5, pady=5) # cria o botão Button(text="F -> C", command= clicouBotaoFC). \ grid(row=0, column=2, padx=5, pady=5) # cria o label Label(text="Graus Celsius:"). \ grid(row=1, column=0, padx=5, pady=5, stick=W) # cria a caixa de texto entryC = Entry(width=10, justify=RIGHT) entryC.grid(row=1, column=1, padx=5, pady=5) # cria o botão Button(text="C -> F", command= clicouBotaoCF). \ grid(row=1, column=2, padx=5, pady=5) # associa métodos para tratar o Enter nas caixas de texto entryF.bind("<Return>", clicouBotaoFC) entryC.bind("<Return>", clicouBotaoCF) mainloop() Texto & Gráfico (textoGrafico.py) Esse programa usa um frame adicional como um dos componentes “colados” no root frame. O root frame usa o Grid como gerenciador de geometria enquanto que o frame interno usa o Pack. from Tkinter import * # espaço entre os retângulos ESPACADOR = 30 # ordenada do próximo retângulo no canvas esquerdo esquerdoY = 10 # ordenada do próximo retângulo no canvas direito direitoY = 10 # método auxiliar para escrever na área de texto def imprime(str): text.config(state=NORMAL) text.insert(END, str + '\n') text.config(state=DISABLED) # trata evento de teclado def apertouEnter(e): imprime("Você escreveu: %s" % caixaTexto.get()) # trata o clique no botao esquerdo def botaoEsquerdo(): global esquerdoY canvasEsquerdo.create_rectangle( 20, esquerdoY, 70, esquerdoY+20, fill='black') esquerdoY += ESPACADOR # trata o clique no botão direito def botaoDireito(): global direitoY canvasDireito.create_rectangle( 20, direitoY, 70, direitoY+20, fill='black') direitoY += ESPACADOR # pega a referência da janela principal para mudar o título da # janela e para impedir o usuário de redimensioná-la root = Tk() root.title("Texto e Gráfico") root.resizable(width=False, height=False) # cria a área de texto à esquerda text = Text(state=DISABLED, width=30) text.grid(row=0, column=0) # cria um canvas no meio canvasEsquerdo = Canvas(bg='white', width=250, height=0) canvasEsquerdo.grid(row=0, column=1, stick=N+S) # cria um canvas à direita canvasDireito = Canvas(bg='white', width=250, height=0) canvasDireito.grid(row=0, column=2, stick=N+S) # cria um frame para colocar caixas de texto e botões # esse frame ocupa tres colunas do grid frame = Frame() frame.grid(row=1, column=0, columnspan=3, stick=W) # um Label Label(frame, text="Some text: ").pack(side=LEFT) # uma caixa de texto caixaTexto = Entry(frame, width=10) caixaTexto.pack(side=LEFT) # um botão Button(frame, text="Draw Left", command=botaoEsquerdo).\ pack(padx=10, side=LEFT) # outro botão Button(frame, text="Draw Right", command=botaoDireito).\ pack(side=LEFT) # associa o evento de teclado a um método caixaTexto.bind("<Return>", apertouEnter) mainloop() Redimensionando o Canvas (redimensionandoCanvas.py) Esse programa desenha um quadrado no centro do canvas. Toda vez que o root frame é redimensionado, o quadrado é redesenhado de modo a ocupar sempre o centro do canvas. # este programa desenha um quadrado centrado no canvas from Tkinter import * BOX_WIDTH = 50 BOX_HEIGHT = 50 def resize(e): canvas.delete(ALL) xc = e.width/2 yc = e.height/2 canvas.create_rectangle(xc - BOX_WIDTH/2, yc - BOX_HEIGHT/2, xc + BOX_WIDTH/2, yc + BOX_HEIGHT/2, fill='black') root = Tk() root.title("Meu programa") canvas = Canvas(bg='white') canvas.pack(fill=BOTH, expand=YES) root.bind('<Configure>', resize) mainloop() Uma loja de CDs (lojaCDs.py) Esse programa apresenta de forma textual e gráfica, o número de CDs de um determinado álbum disponíveis em uma loja de CDs. A base de dados é mantida em um arquivo texto que é lido pelo programa no início do processamento. O canvas usado para mostrar as informações pedidas, é redesenhado toda vez que o frame principal (root) é redimensionado. O arquivo contendo a base de dados (music.txt) Os dados são armazenados na forma: [nome do álbum] [artista] número_de_cópias_disponíveis [Eagles/Greatest Hits] [The Eagles] 10 [Thriller] [Michael Jackson] 12 [The Wall] [Pink Floyd] 2 [Led Zeppelin IV] [Led Zeppelin] 10 [Billy Joel Greatest Hits] [Billy Joel Greatest Hits] 20 [Back In Black] [AC/DC] 15 [The Beatles] [The Beatles] 7 [The Bodyguard] [Whitney Houston] 8 [Elton John Greatest Hits] [Elton John] 14 [Hotel California] [The Eagles] 20 Os dados individuais de cada álbum serão mantidos em Lists na forma: [nome_do_álbum, artista, número_de_cópias_disponíveis] O conjunto dos álbuns é carregado para a memória principal e mantido em um dicionário onde a chave é o nome do álbum e o valor a lista contendo os dados do álbum. Algo do tipo: {'Eagles/Greatest Hits': ['Eagles/Greatest Hits', 'The Eagles', 10], 'Billy Joel Greatest Hits': ['Billy Joel Greatest Hits', 'Billy Joel Greatest Hits', 20], 'Hotel California': ['Hotel California', 'The Eagles', 20], 'The Beatles': ['The Beatles', 'The Beatles', 7], 'Elton John Greatest Hits': ['Elton John Greatest Hits', 'Elton John', 14], 'The Bodyguard': ['The Bodyguard', 'Whitney Houston', 8], 'Led Zeppelin IV': ['Led Zeppelin IV', 'Led Zeppelin', 10], 'Back In Black': ['Back In Black', 'AC/DC', 15], 'The Wall': ['The Wall', 'Pink Floyd', 2], 'Thriller': ['Thriller', 'Michael Jackson', 12]} Esse dicionário é armazenado em um dicionário chamado inventario. inventario = {} O pseudocódigo do algoritmo para a leitura dos dados é dado por: Para cada linha do arquivo de entrada: extrai da linha lida o nome do álbum, o nome da banda e o número de cópias disponíveis cria uma lista na forma: álbum = [álbum, banda, número de cópias] insere o novo álbum no dicionário fazendo: inventário[álbum] = album Esse pseudo-código foi implementado em uma função chamada carregaInventario() def carregaInventario(): arq = open("music.txt") for linha in arq: album = analisaLinha(linha) # inventario é um dicionário cuja chave é o nome do álbum inventario[album[0]] = album arq.close() A função analisaLinha() recebe uma string correspondente à linha lida, extrai dessa string as informações necessárias (álbum, artista e número de cópias) e retorna uma lista contendo essas informações. def analisaLinha(linha): # procura informações em uma linha do tipo # [álbum] [banda] numItens iNomeAlbum = linha.find("[") + 1 fNomeAlbum = linha.find("]") nomeAlbum = linha[iNomeAlbum:fNomeAlbum] iNomeBanda = linha.find("[", fNomeAlbum + 1) + 1 fNomeBanda = linha.find("]", fNomeAlbum + 1) nomeBanda = linha[iNomeBanda:fNomeBanda] numItensEstoque = int(linha[fNomeBanda + 1:].strip()) return [nomeAlbum, nomeBanda, numItensEstoque] O programa em execução (lojaCDs.py)A interface gráfica com o usuário e os métodos de callback inventario = {} carregaInventario() ultimoAlbum = None root = Tk() root.title("Loja de Música") canvas = Canvas(bg='white') canvas.pack(fill=BOTH, expand=YES) label = Label(text="Nome do Álbum") label.pack(padx=5, side=LEFT) entry = Entry(width=20) entry.pack(padx=5, side=LEFT) entry.bind("<Return>", apertouEnter) root.bind('<Configure>', redimensionou) mainloop() O evento de call-back chamado quando o usuário aperta o Enter na caixa de texto def apertouEnter(e): global ultimoAlbum try: ultimoAlbum = inventario[entry.get().upper()] except (KeyError): ultimoAlbum = None mostraInventario(ultimoAlbum) A função mostraInventario() mostra o estado do estoque de maneira textual e gráfica def mostraInventario(album): canvas.delete(ALL) if album != None: numItensEstoque = album[2] canvas.create_text( ESPACAMENTO, (canvas.winfo_height() - ALTURA_BARRA)/2 – ESPACAMENTO, text="Álbum [%s] por [%s]" % (album[0], album[1]), anchor=SW ) # mostra quadrados indicando quantos itens há no estoque proximoX = ESPACAMENTO larguraBarra = (canvas.winfo_width()–ESPACAMENTO)/MAX_ESTOQUE - \ ESPACAMENTO for i in range(numItensEstoque): canvas.create_rectangle( proximoX, (canvas.winfo_height() - ALTURA_BARRA) / 2, proximoX + larguraBarra, (canvas.winfo_height() + ALTURA_BARRA) / 2, fill = 'black' ) proximoX += larguraBarra + ESPACAMENTO canvas.create_text( ESPACAMENTO, (canvas.winfo_height() + ALTURA_BARRA)/2 + ESPACAMENTO, text="%d no estoque" % numItensEstoque, anchor=NW ) O método de call-back chamado quando o frame principal é redimensionado. def redimensionou(e): mostraInventario(ultimoAlbum) Apêndice: O programa completo. # -*- coding: cp1252 -*- from Tkinter import * ALTURA_BARRA = 20 ESPACAMENTO = 10 MAX_ESTOQUE = 20 def analisaLinha(linha): iNomeAlbum = linha.find("[") + 1 fNomeAlbum = linha.find("]") nomeAlbum = linha[iNomeAlbum:fNomeAlbum] iNomeBanda = linha.find("[", fNomeAlbum + 1) + 1 fNomeBanda = linha.find("]", fNomeAlbum + 1) nomeBanda = linha[iNomeBanda:fNomeBanda] iNumItensEstoque = linha.find(" ", fNomeBanda + 1) + 1 numItensEstoque = int(linha[iNumItensEstoque:-1]) return [nomeAlbum, nomeBanda, numItensEstoque] def carregaInventario(): arq = open("music.txt") for linha in arq: album = analisaLinha(linha) # inventario é um dicionário cuja chave é o nome do álbum inventario[album[0].upper()] = album arq.close() def mostraInventario(album): canvas.delete(ALL) if album != None: numItensEstoque = album[2] canvas.create_text( 10, (canvas.winfo_height() - ALTURA_BARRA)/2 - ESPACAMENTO, text="Álbum [%s] por [%s]" % (album[0], album[1]), anchor=SW ) # mostra quadrados indicando quantos itens há no estoque proximoX = ESPACAMENTO larguraBarra = (canvas.winfo_width()-ESPACAMENTO)/MAX_ESTOQUE - \ ESPACAMENTO for i in range(numItensEstoque): canvas.create_rectangle( proximoX, (canvas.winfo_height() - ALTURA_BARRA) / 2, proximoX + larguraBarra, (canvas.winfo_height() + ALTURA_BARRA) / 2, fill = 'black' ) proximoX += larguraBarra + ESPACAMENTO canvas.create_text( ESPACAMENTO, (canvas.winfo_height() + ALTURA_BARRA)/2 + ESPACAMENTO, text="%d no estoque" % numItensEstoque, anchor=NW ) def apertouEnter(e): global ultimoAlbum try: ultimoAlbum = inventario[entry.get().upper()] except (KeyError): ultimoAlbum = None mostraInventario(ultimoAlbum) def redimensionou(e): mostraInventario(ultimoAlbum) inventario = {} carregaInventario() ultimoAlbum = None root = Tk() root.title("Loja de Música") canvas = Canvas(bg='white') canvas.pack(fill=BOTH, expand=YES) label = Label(text="Nome do Álbum") label.pack(padx=5, side=LEFT) entry = Entry(width=20) entry.pack(padx=5, side=LEFT) entry.bind("<Return>", apertouEnter) root.bind('<Configure>', redimensionou) mainloop()