# Gera a página principal a partir do modelo "index.html" return cherrytemplate.renderTemplate(file='index.html', outputEncoding='utf-8') @cherrypy.expose def add(self): """ Cadastra novos registros """ # Gera a página de registro novo a partir do modelo "add.html" return cherrytemplate.renderTemplate(file='add.html', outputEncoding='utf-8') @cherrypy.expose def rem(self, ident): """ Confirma a remoção de registros """ 164 MVC # Seleciona o registro sel = zoo.select(zoo.c.id==ident) rec = sel.execute() res = rec.fetchone() # Gera a página de confirmar exclusão a partir do modelo "rem.html" return cherrytemplate.renderTemplate(file='rem.html', outputEncoding='utf-8') @cherrypy.expose def mod(self, ident): """ Modifica registros """ # Seleciona o registro sel = zoo.select(zoo.c.id==ident) rec = sel.execute() res = rec.fetchone() # Gera a página de alteração de registro a partir do modelo "mod.html" return cherrytemplate.renderTemplate(file='mod.html', outputEncoding='utf-8') # Inicia o servidor na porta 8080 cherrypy.quickstart(Root()) Modelo “index.html” (página principal): <py-include="header.html"> <table> <tr> <th></th> <py-for="coluna in colunas"> <th><py-eval="coluna"></th> </py-for> <th></th> <th></th> </tr> <py-for="i, campos in enumerate(rec.fetchall())"> <tr> <th><py-eval="unicode(i + 1)"></th> <py-for="coluna in colunas"> <td><py-eval="unicode(campos[coluna])"></td> </py-for> <td> <a href="/mod?ident=<py-eval="unicode(campos['id'])">">modificar</a> </td><td> <a href="/rem?ident=<py-eval="unicode(campos['id'])">">remover</a> </td> </tr> </py-for> MVC 165 </table> <br /> <form action="/add" method="post"> <input type="submit" value=" adicionar " /> </form> <p> <py-eval="msg"> </p> <py-include="footer.html"> Modelo “add.html” (página de formulário para novos registros): <py-include="header.html"> <form action="/?op=add" method="post"> <table> <py-for="coluna in colunas"> <tr><td> <py-eval="coluna"> </td><td> <input type="text" size="30" name="<py-eval="coluna">" /> </td></tr> </py-for> </table> <br /> <input type="submit" value=" salvar " /> </form> <br /> [ <a href="/">voltar</a> ] <py-include="footer.html"> Modelo “mod.html” (página de formulário para alteração de registros): <py-include="header.html"> <form action="/?op=mod&ident=<py-eval="unicode(res['id'])">" method="post"> <table border="0"> <py-for="coluna in colunas"> <tr><th> <py-eval="coluna"> </th><td> <input type="text" size="30" name="<py-eval="coluna">" value="<py-eval="unicode(res[coluna])">" /> </td></tr> </py-for> </table> <br /> <input type="submit" value=" salvar " /> </form> <br /> [ <a href="/">voltar</a> ] 166 MVC <py-include="footer.html"> Modelo “rem.html” (página que pede confirmação para remoção de registros): <py-include="header.html"> <table border="1"> <tr> <py-for="coluna in colunas"> <th><py-eval="coluna"></th> </py-for> </tr> <tr> <py-for="coluna in colunas"> <td><py-eval="unicode(res[coluna])"></td> </py-for> </tr> </table> <br /> <form action="/?op=rem&ident=<py-eval="unicode(res['id'])">" method="post"> <input type="submit" value=" remover " /> </form> <br /> [ <a href="/">voltar</a> ] <py-include="footer.html"> Modelo “header.html” (cabeçalho comum a todos os modelos): <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> <title>Zoo</title> <style type="text/css"> <!-- body { margin: 10; padding: 10; font: 80% Verdana, Lucida, sans-serif; color: #333366; } h1 { margin: 0; padding: 0; font: 200% Lucida, Verdana, sans-serif; } a { color: #436976; text-decoration: none; } MVC 167 a:hover { background: #c4cded; text-decoration: underline; } table { margin: 1em 0em 1em 0em; border-collapse: collapse; border-left: 1px solid #858ba1; border-bottom: 1px solid #858ba1; font: 90% Verdana, Lucida, sans-serif; } table th { padding: 0em 1em 0em 1em; border-top: 1px solid #858ba1; border-bottom: 1px solid #858ba1; border-right: 1px solid #858ba1; background: #c4cded; font-weight: normal; } table td { padding: 0em 1em 0em 1em; border-top: 1px solid #858ba1; border-right: 1px solid #858ba1; text-align: center; } form { margin: 0; border: none; } input { border: 1px solid #858ba1; background-color: #c4cded; vertical-align: middle; } --> </style> </head> <body> <h1>Zoo</h1> <br /> Modelo “footer.html” (rodapé comum a todos os modelos): </body> </html> Página principal: 168 MVC Exercícios V 169 Exercícios V 1. Implementar uma classe Animal com os atributos: nome, espécie, gênero, peso, altura e idade. O objeto derivado desta classe deverá salvar seu estado em arquivo com um método chamado “salvar” e recarregar o estado em um método chamado “desfazer”. 2. Implementar uma função que formate uma lista de tuplas como tabela HTML. 3. Implementar uma aplicação Web com uma saudação dependente do horário (exemplos: “Bom dia, são 09:00.”, “Boa tarde, são 13:00.” e “Boa noite, são 23:00.”). 4. Implementar uma aplicação Web com um formulário que receba expressões Python e retorne a expressão com seu resultado. 170 Parte VI Parte VI ▪ Interface gráfica. ▪ Threads. ▪ Processamento distribuído. ▪ Performance. ▪ Exercícios VI. Interface Gráfica 171 Interface Gráfica As Interfaces Gráficas com Usuário (GUI, Graphic User Interface) se popularizaram no ambiente desktop, devido à facilidade de uso e a produtividade. Existem hoje muitas bibliotecas disponíveis para a construção de aplicações GUI, tais como: GTK+, QT, TK e wxWidgets. O GTK+52 (GIMP Toolkit) é uma biblioteca Open Source escrita em linguagem C. Originalmente concebida para ser usada pelo GIMP53, é compatível com as plataformas mais utilizadas atualmente e rica em recursos, entre eles, um construtor de interfaces chamado Glade. Interface do Glade: O GTK+ é usado pelo GNOME54 (ambiente desktop Open Source) e por diversas aplicativos, como os portes do Mozilla Firefox e do BrOffice.org para sistemas UNIX. O GTK+ pode ser 52 A página internet do projeto reside em: http://www.gtk.org/. e os binários para Windows estão disponíveis em: http://gladewin32.sourceforge.net/. A versão para desenvolvedores instala o Glade. 53 Endereço oficial do projeto: http://www.gimp.org/. 54 Documentação e fontes em: http://www.gnome.org/. 172 Interface Gráfica usado no Python através do pacote PyGTK55. Os portes das bibliotecas para Windows podem ser encontrados em: ▪ PyGTK: http://ftp.gnome.org/pub/gnome/binaries/win32/pygtk/ ▪ PyGObject: http://ftp.gnome.org/pub/gnome/binaries/win32/pygobject/ ▪ PyCairo: http://ftp.gnome.org/pub/gnome/binaries/win32/pycairo/ Arquitetura Interfaces gráficas geralmente utilizam a metáfora do desktop, um espaço em duas dimensões, é que ocupado por janelas retangulares, que representam aplicativos, propriedades ou documentos. As janelas podem conter diversos tipos de controles (objetos utilizados para interagir com o usuário ou para apresentar informações) e containers (objetos que servem de repositório para coleções de outros objetos). A interface gráfica deve ficar esperando