programação

Comparativo de IDEs online de HTML5

IDEs para HTML5

Uma das formas mais bacanas de trabalhar com criação em HTML5 hoje em dia (pelo menos de iniciar projetos menores e utilitários) é usando um serviço de editor online. Neles, você pode editar código, testar a vontade e até salvar na própria ferramenta (ganhando uma URL impronunciável, mas com o seu código salvo "nela"). Aqui apresento algumas ferramentas interessantes para isso:

  • CodePen - Editor que oferece edição do HTML, CSS e JavaScript, exibindo o resultado abaixo das áreas de edição. Oferece um plano pago, que permite upload de arquivos, modo colaborativo e modo professor.
  • JS Bin - Cinco áreas disponíveis: HTML, CSS, JavaScript, Console e Output. O mais completo nesse aspecto. Ainda não o utilizei de fato.
  • jsdo.it - Seria uma excelente ferramenta, não fosse um bug muito inconveniente. Nele, você se cadastra e cria projetos. Um projeto pode referenciar outro projeto, o que é bastante útil quando lidamos com bibliotecas e aplicativos de forma separada. Permite também fazer upload, o que dá condições de fazermos jogos em HTML5, mandando imagens e sons para lá. Ele também faz verificação do código escrito, com um depurador JavaScript rodando no cliente deles. O bug de que falei entra justamente aí. A opção Salvar aparentemente não salva, salva apenas para efeito de teste. Nos meus testes, perdi dois dias de trabalho por confiar nessa opção Salvar...
  • jsfiddle - O mais popular. Divide a tela em 4 áreas: HTML, CSS, JavaScript e Result. Poderiam oferecer um modo de atualização automática do "Result", mas é uma excelente ferramenta. O grande diferencial é a disponibilidade de várias versões diferentes para as mesmas bibliotecas.
  • Liveweave - Divide a área em 4 como o jsfiddle, mas com a vantagem de atualização em tempo real, também com opção de desativar tal recurso. Considero um dos melhores.
  • Reloado - Área de JavaScript e de HTML. O usuário escolhe se quer visualizar o resultado em tempo real, a cada mudança, ou se prefere ficar clicando no botão Render. Dos melhores, na minha opinião.

Bem, agora o principal: um comparativo entre eles (adoro essas tabelas-comparison), considerando as bibliotecas oferecidas para fácil inclusão, por padrão, em cada um:

 

CodePen

jsbin

jsdo

jsfiddle

liveweave

reloado

Angular JS

 

1.2.1

1.1.5

1.0.7

1.0.3

1.2.1

1.1.1

1.0.7

 

Arctic JS

 

 

20120123

 

 

 

Backbone

 

latest

1.0.0

1.0

latest

0.9.1

Bootstrap

 

latest

2.3.2

3.0.0

2.2.2

 

latest

latest

Bonsai

 

0.4.latest

 

0.4.1

 

 

Brick

 

 

 

edge

 

 

CanJS

 

2.0.3

 

 

 

 

Cannon JS

 

 

0.4.3

 

 

 

Chart JS

 

 

 

 

0.2

 

CoffeScript

 

Não-identificada

 

 

 

Não-identificada

Create JS

 

 

2013-02-12

Não-identificada

latest

 

D3

 

3.x

 

3.0.4

3.0

 

Dojo

latest

latest

1.8.4

1.7.4

1.7.3

1.9.0

1.8.4

1.7.4

1.6

1.5

nightly

latest

1.6.0

Dijit

 

latest

1.8.4

1.7.4

 

 

 

 

Ember

 

1.0.0

 

 

1.1.2

 

Enchant.js

 

 

0.70

 

 

 

Enyo JS

 

latest

2.2.0

2.2.0

2.1

2.0.1

nightly

 

latest

 

ES5 shim

 

2.0.8

 

 

 

1.2.4

Ext-core

 

3.1.0

 

 

 

3.1.0

Ext JS

latest

 

4.0.2

4.2.0

4.1.1

4.1.0

3.4.0

3.1.0

3.0.0

4.2.0

 

Ext JS all

 

 

4.0.7

 

 

 

Fabric JS

 

 

 

1.4.0

1.2.0

0.9

1.3.0

 

Font Awesome

 

4.0.3

 

 

 

 

Foundation

 

5.0.3

 

 

 

 

Handlebars.js

 

1.0.0

 

 

 

 

HTML5 shiv

 

Não-identificada

 

 

 

 

jPlayer

 

 

2.2.0

 

 

 

Jquery

latest

2.x WIP

2.0.3

1.x WIP

1.10.2

1.9.1

1.8.3

2.0.3

1.10.2

1.8.3

2.x (edge)

2.0.2

1.x (edge)

1.9.1

1.8.3

1.7.2

1.6.4

1.10.1

latest

latest

WIP

1.7.2

1.6.4

Jquery Easing

 

 

1.3

 

 

 

Jquery UI

latest

WIP

1.10.4

1.9.2

1.10.3

1.10.3

latest

1.8.13

Jquery-migrate

 

1.2.1

 

1.2.1

 

 

Jquery Mobile

 

WIP

1.4.0

1.3.2

1.2.1

1.1.2

 

1.3.1

latest

latest

1.0.1

1.1.0rc1

Jquery Tools

 

 

 

 

1.2.7

 

JSDeferred

 

 

0.3.4

 

 

 

JsdoitController

 

 

Não-Identificada

 

 

 

JSX Transformer

 

 

 

0.4.0

 

 

Jtypes

 

 

 

2.1.0

 

 

Kendo UI

 

Q3

Q2

 

 

 

 

Kinetic JS

 

 

 

4.3.1

4.0.5

4.7.3

 

Knockout JS

 

2.2.1

2.1.0

3.0.0

2.3.0

2.2.1

2.1.0

2.0.0

3.0.0

 

Less

 

1.3.3

 

 

 

1.1.3

Lodash

 

1.2.1

 

2.2.1

 

 

Lungo

 

Não-identificada

 

 

 

 

Marionette JS

 

latest

 

 

 

 

Minified

 

 

 

1.0 Beta 1

 

 

Modernizr

 

2.6.2

 

 

latest

2.5.3

Moo Tools

latest

latest

1.4.5

1.4.2

1.4.5

1.3.2

nightly

latest

1.3.2

1.2.4

Moo Tools More

 

 

1.4.0.1

1.4.0.1

 

 

OrbiterMicro

 

 

1.1.0.514

 

 

 

Paper JS

 

 

 

0.22

0.9.9

 

Polymer

 

0.1.1

 

 

 

 

Power Tools

 

 

 

1.2.0

 

 

Prefixfree

 

1.0.7

 

 

 

 

Processing JS

 

1.4.1

1.4.0

1.4.1

1.3.6

1.2.3

1.4.1

1.2.3

Prototype JS

latest

latest

1.7.1

1.6.1.0

1.7

1.7.1

1.6.1.0

latest

latest

1.7.0.0

1.6.1.0

Pure CSS

 

 

 

 

0.30

 

Qooxdoo

 

 

 

2.1

2.0.3

3.0.1

 

Qunit

 

latest

 

 

 

 

Raphael JS

 

2.1.0

1.5.2

2.1.0

1.5.2

1.4

2.1.0

2.0.0

React

 

0.8.0

 

0.4.0

0.3.2

 

 

RightJS

 

 

 

2.3.1

2.1.1

 

 

Sammy

 

0.7.4

 

 

 

0.6.3

Script.aculo.us

 

latest

1.8.3

 

1.9

latest

1.8.3

Scripty

 

 

 

2.0b1

 

 

Sencha Touch

 

Não-identificada

2.0.0-gpl

 

 

Não-identificada

Shipyard

 

 

 

0.2

nightly

 

 

Snap SVG

 

 

 

 

latest

 

Socket.IO

 

 

0.8.7

 

 

 

SVG JS

 

 

 

0.x

latest

 

SWFObject

 

 

2.2

 

 

 

Thorax

 

 

 

2.0.0rc6

2.0.0rc3

 

 

Three JS

 

r58

r60

r54

latest

 

Tmlib JS

 

 

0.1.5

 

 

 

Traceur

 

Não-identificada

 

 

 

 

TwitterLib

 

Não-identificada

 

 

 

Não-identificada

Underscore JS

 

Não-identificada

1.4.4

1.4.4

1.4.3

1.3.3

latest

1.3.1

Web App Install

 

 

 

0.1

 

 

Web Font Loader

 

 

 

 

1.4.10

 

X Toolkit

 

 

 

edge

 

 

YUI

latest

3.10.0

2.9.0

3.3.0

3.8.0

3.7.3

3.6.0

3.5.0

3.4.1

3.14.0

3.10.1

2.8.0r4

3.13.0

3.3.0

2.8.2

Zepto

latest

latest

1.0

 

1.0rc1

latest

0.7

Programação: Criando ovos de píton (easy_install)

Ovos de cobra

Se você não tem nada a ver com programação, nem tem interesse no assunto, simplesmente ignore este artigo.


Mike Driscoll tem um blog dedicado a Python chamado The Mouse vs. the Python e eventualmente há excelentes artigos por lá.
Esta é uma tradução livre do artigo Python 101: esay_install or how to create eggs e modifiquei sutilmente algumas coisas, incluindo os exemplos. Agradeço ao Mike pelos excelentes artigos e me desculpo pelas liberdades que tomei na tradução (incluindo a mudança no nome do artigo). Vamos lá então!


Hoje daremos uma olhada no controverso método easy_install de instalar módulos e pacotes Python. Também aprenderemos como criar nossos próprios arquivos *.egg. Você precisará do pacote Setup Tools para fazer isso tudo. Esse pacote não suporta Python 3.x, assim se você precisar dessa versão do Python, veja pip. Haverá artigos desses projetos no futuro. Por ora, começaremos com o SetupTools e o easy_install.

Por que é controverso? Não estou de todo certo, mas as pessoas não parecem felizes com a forma como se pacotes instalam pela metade quando elas não esperam o download terminar. Pra completar, o autor não parece lá muito interessado em atualizar o pacote ou permitir que alguém o faça. Veja o artigo de Ziade no fim deste post.

SetupTools é o método principal e original de baixar e instalar pacotes Python pelo PyPI e outras fontes via linha de comando, tipo um apt-get para Python. Quando você instala o SetupTools, ele instala um script ou executável chamado easy_install, que você invocará na linha de comando para instalar ou atualizar pacotes. Ele também fornece uma forma de criar ovos de Python. Vamos gastar mais um tempinho para entender melhor essa funcionalidade.

Usando easy_install para instalar Pacotes

Uma vez que você tenha SetupTools instalado, você deve tê-lo no seu caminho. Isso quer dizer que você tem que estar pronto para abrir um terminal (Linux) ou linha de comando (Windows) e simplesmente executar easy_install. Um exemplo de invocação:

easy_install sqlalchemy

Isso pedirá ao PyPI que tente baixar o SQLAlchemy mais recente do repositório dele ou de qualquer outro para o qual o pacote PyPI aponte. O easy_install o instalará. Um

Um problema comumente criticado do easy_install é que ele pode tentar instalar o pacote antes mesmo de concluir seu download, o que leva a problemas e instalações defeituosas. O legla é que se você configurar corretamente o seu setup.py, o easy_install vai baixar também todas as dependências necessárias, instalando-as também. Assim, se você instalar algo complexo, como o TurboGears, você verá o easy_install instalar um bocado de pacotes. Essa é uma razão pela qual você pode querer usar virtualenv para ter certeza de que gosta de todos esses pacotes e de que eles funcionam a contento. Se não funcionarem, você simplesmente apaga a pasta virtualenv. De outro modo, você terá que ir na sua própria pasta do Python e cavar por ali para tentar "desinstalar" (ou seja, deletar pastas) por sua conta. A outra coisa legal que o easy_install faz quando instala os ovos é que ele adiciona o ovo a um arquivo easy_install.pth em site-packages, de modo que quando você o desinstalar, precise editar esse arquivo também. Felizmente, você pode usar pip para desinstalá-lo se você não tiver criado as pastas sozinho. Há um comando -uninstall (-u), mas eu já ouvi relatos contraditórios sobre seu funcionamento.

Você pode instalar um pacote passando uma url diretamente ao easy_install. Outro recurso maneiro é que você pode dizer ao easy_install qual versão você quer e ele tentará instalá-la. Finalmente, easy_install pode instalar tanto a partir de arquivos de código-fonte quanto de ovos (arquivos .egg). Para uma lista completa dos comandos, você deve ler a documentação.

Criando um ovo

Um arquivo egg é um formato de distribuição para pacotes Python. É uma alternativa à distribuição de fontes ou executáveis do Windows, mas perceba que módulos em Python puro são multiplatafroma! Daremos uma olhada em como criar nosso próprio ovo usando o pacote que criamos no tutorial sobre criação de módulos (que ainda não traduzi :-( ). Crie uma nova pasta e coloque a pasta mymath dentro dela. Crie um arquivo setup.py no diretório pai do mymath com o seguinte conteúdo:

from setuptools import setup, find_packages
 
setup(
    name = "mymath",
    version = "0.1",
    packages = find_packages()
    )

Perceba que ao invés de usar a função setup do distutils, usamos o setup do setuptools. Também usamos a função find_packages do setuptoos, que procurará automaticamente por pacotes no diretório corrente e os adicionará ao ovo. Para criar o tal do ovo, você só precisa digitar essa linha de comando:

python setup.py bdist_egg

Isso gera um monte de saída, mas quando tudo estiver ok você vai ver três novas pastas: build, dist e mymath.egg-info. A única que nos interessa é a pasta dist, onde você achará o ovo, mymath-0.1-py2.6.egg. Note que na minha máquina, ele faz referência ao meu Python padrão, que era o 2.6, e cria o ovo para essa versão do Python. O ovo em si é basicamente um arquivo zip. Se você mudar sua extensão para "zip", poderá fuçar por dentro dele e ver que ele tem duas pastas: mymath e EGG-INFO. A partir daqui, você já pode apontar com o easy_install para o seu ovo no sistema de arquivos e assim instalar seu pacote.

Se quiser, vocêm pode usar o easy_install para enviar seu ovo ou fonte diretamente para o Python Package Index (PyPI), usando o seguinte comando (copiado da documentação):

setup.py bdist_egg upload # cria um ovo e o envia
setup.py sdist upload # cria uma distribuição de fonte e a envia
setup.py sdist bdist_egg upload # cria ambos e os envia

Conclusão

Agora você está apto a usar o easy_install ou sabe o suficiente para tentar uma das alternativas. Pessoalmente, tive alguns problemas com ele e não pretendo usá-lo. Porém, daremos uma olhada no pip e sobre distribuição em breve, em artigo futuro. Por enquanto, dê uma chance ao easy_install e veja o que conclusão você tira, ou me conte suas histórias de terror nos comentários!

Leia também (em Inglês)

P. S.: Foto usada no post: 1st Batch Corn Hatching, de Viper76

wxPython: Como criar um assistente genérico

Se você não tem nada a ver com programação, nem tem interesse no assunto, simplesmente ignore este artigo.


Mike Driscoll tem um blog dedicado a Python chamado The Mouse vs. the Python e eventualmente há excelentes artigos por lá.

Esta é uma tradução livre do artigo wxPython: How to Create a Generic Wizard e modifiquei sutilmente algumas coisas, incluindo os exemplos. Agradeço ao Mike pelos excelentes artigos e me desculpo pelas liberdades que tomei na tradução (incluindo a mudança no nome do artigo). Vamos a ele!


Outro dia eu vi no StackOverflow alguém brigando com o widget Wizard, do wxPython. O wizard não permite muita personalização quando se trata dos seus botões, assim eu decidi ver quão difícil seria escrever meu próprio assistente. Este código é bastante limitado, mas aqui está minha primeira versão beta:

# coding: utf-8
import wx
 
########################################################################
class WizardPage(wx.Panel):
    """"""
 
    #----------------------------------------------------------------------
    def __init__(self, parent, title=None):
        """Construtor"""
        wx.Panel.__init__(self, parent)
 
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(sizer)
 
        if title:
            title = wx.StaticText(self, -1, title)
            title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
            sizer.Add(title, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
            sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.ALL, 5)
 
 
########################################################################
class WizardPanel(wx.Panel):
    """"""
 
    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Construtor"""
        wx.Panel.__init__(self, parent=parent)
        self.pages = []
        self.page_num = 0
 
        self.mainSizer = wx.BoxSizer(wx.VERTICAL)
        self.panelSizer = wx.BoxSizer(wx.VERTICAL)
        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
 
        # adiciona os botões de voltar/avançar
        self.prevBtn = wx.Button(self, label="Voltar")
        self.prevBtn.Bind(wx.EVT_BUTTON, self.onPrev)
        btnSizer.Add(self.prevBtn, 0, wx.ALL|wx.ALIGN_RIGHT, 5)
 
        self.nextBtn = wx.Button(self, label="Avançar")
        self.nextBtn.Bind(wx.EVT_BUTTON, self.onNext)
        btnSizer.Add(self.nextBtn, 0, wx.ALL|wx.ALIGN_RIGHT, 5)
 
        # conclui o leiaute
        self.mainSizer.Add(self.panelSizer, 1, wx.EXPAND)
        self.mainSizer.Add(btnSizer, 0, wx.ALIGN_RIGHT)
        self.SetSizer(self.mainSizer)
 
 
    #----------------------------------------------------------------------
    def addPage(self, title=None):
        """"""
        panel = WizardPage(self, title)
        self.panelSizer.Add(panel, 2, wx.EXPAND)
        self.pages.append(panel)
        if len(self.pages) > 1:
            # esconde todos os painéis depois do primeiro
            panel.Hide()
            self.Layout()
 
    #----------------------------------------------------------------------
    def onNext(self, event):
        """"""
        pageCount = len(self.pages)
        if pageCount-1 != self.page_num:
            self.pages[self.page_num].Hide()
            self.page_num += 1
            self.pages[self.page_num].Show()
            self.panelSizer.Layout()
        else:
            print "Fim das páginas!"
 
        if self.nextBtn.GetLabel() == "Concluir":
            # fecha o aplicativo
            self.GetParent().Close()
 
        if pageCount == self.page_num+1:
            # muda a etiqueta
            self.nextBtn.SetLabel("Concluir")
 
    #----------------------------------------------------------------------
    def onPrev(self, event):
        """"""
        pageCount = len(self.pages)
        if self.page_num-1 != -1:
            self.pages[self.page_num].Hide()
            self.page_num -= 1
            self.pages[self.page_num].Show()
            self.panelSizer.Layout()
        else:
            print "Você já está na primeira página!"
 
 
########################################################################
class MainFrame(wx.Frame):
    """"""
 
    #----------------------------------------------------------------------
    def __init__(self):
        """Construtor"""
        wx.Frame.__init__(self, None, title="Assistente Genérico", size=(800,600))
 
        self.panel = WizardPanel(self)
        self.panel.addPage("Página 1")
        self.panel.addPage("Página 2")
        self.panel.addPage("Página 3")
 
        self.Show()
 
if __name__ == "__main__":
    app = wx.App(False)
    frame = MainFrame()
    app.MainLoop()

O frame principal instancia nosso painel principal (WizardPanel). Aqui é onde entra a maior parte do nosso código. Ele controla a paginação para a frente e para trás pelas páginas do assistente. Você pode definir as páginas do assistente da maneira que desejar. De fato, o que posso fazer numa segunda versão é fazer com que trabalhe com uma classe Panel de minha própria autoria, já que usar páginas simples como eu fiz o torna bastante limitado. De qualquer maneira, adicionei 3 páginas e testei as iterações entre elas. Espero que outros achem isso interessante também. Divirtam-se!

wxPython: Tudo sobre menus

Se você não tem nada a ver com programação, nem tem interesse no assunto, simplesmente ignore este artigo.


Mike Driscoll tem um blog dedicado a Python chamado The Mouse vs. the Python e eventualmente há excelentes artigos por lá.

Esta é uma tradução livre do artigo wxPython: All about menus e modifiquei sutilmente algumas coisas, incluindo os exemplos. Agradeço ao Mike pelos excelentes artigos e me desculpo pelas liberdades que tomei na tradução (incluindo a mudança no nome do artigo). Vamos a ele!


Menus são onipresentes. Eles estão praticamente em quase os programas para desktop. Você os usa para editar preferências ou configurar seu programa. Em wxPython, há várias opções de menu para se escolher. A mais familiar é provavelmente wx.Menu. Mas há menus popup e uma implementação própria do Python conhecida como FlatMenu. Nós cobriremo aqui o wx.Menu e os menus popup porque ambos estão relacionados. FlatMenu inclui a API toolbar, assim você vai ter que esperar por um outro artigo que trate exclusivamente desses widgets. Então vamos começar a festa dos menus!

Um Exemplo Simples de Menu

Um exemplo simples de menu

Vamos começar com algo realmente simples. Um menu que só tem uma opção: Sair. Veja o código:

import wx
 
########################################################################
class MyForm(wx.Frame):
    """"""
 
    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title="Tutorial wx.Menu")
 
        self.panel = wx.Panel(self, wx.ID_ANY)
 
        menuBar = wx.MenuBar()
        fileMenu = wx.Menu()
        exitMenuItem = fileMenu.Append(wx.NewId(), "Sair",
                                       "Sair do programa")
        menuBar.Append(fileMenu, "&Arquivo")
        self.Bind(wx.EVT_MENU, self.onExit, exitMenuItem)
        self.SetMenuBar(menuBar)
 
    #----------------------------------------------------------------------
    def onExit(self, event):
        """"""
        self.Close()
 
#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm().Show()
    app.MainLoop()

Vamos detalhar melhor isso mais adiante. Para criarmos a barra de menu, instanciamos wx.MenuBar. Então criamos uma instância de wx.Menu, che chamamos de filemenu. Finalmente, adicionamos o item "Sair". Em essência, nós empilhamos wx.MenuItem, mas isso foi um tipo de atalho, já que não chegamos a instanciar um wx.MenuItem primeiro. Nós mostraremos como fazer isso no nosso próximo exemplo. Note que ao adicionarmos um item, temos que passar um id, uma string de etiqueta e uma string de estado. Esta última será mostrada quando você posicionar o mouse sobre o item de menu, desde que você tenha uma barra de estado. Not que para anexar um manipulador de eventos ao item de menu, você precisa usar o evento EVT_MENU e vinculá-lo ao frame. A seguir adicione o Menu propriamente ao objeto MenuBar e passe uma string também, que é neste caso "Arquivo". Finalmente, chamamos o método SetMenuBar do frame para anexar a barra de menu ao frame.

Adicionando uma imagem ao menu

Isso é tudo o que é preciso para criarmos um menu! Agora vamos mostrar um exemplo mais complex! Nota: para seguir o exemplo abaixo, você precisará usar seu próprio arquivo de imagem.

wx.Menu Imagem

# coding: utf-8
import wx
 
########################################################################
class MyForm(wx.Frame):
    """"""
 
    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title="Tutorial wx.Menu")
 
        self.panel = wx.Panel(self, wx.ID_ANY)
 
        # create the menubar
        menuBar = wx.MenuBar()
 
        # create the first menu (starting on left)
        carMenu = wx.Menu()
        carMenu.Append(101, "&Ford", "Fabricante estadunidense")
        carMenu.Append(102, "&Nissan", "")
        carMenu.Append(103, "&Toyota", "Japoneses!")
        carMenu.Append(104, "&Sair", "Fechar a aplicação")
 
        # add a picture to a menu
        picMenu = wx.Menu()
        item = wx.MenuItem(picMenu, wx.ID_ANY, "Cobra", "Este menu tem uma imagem!")
        img = wx.Image('snake32.png', wx.BITMAP_TYPE_ANY)
        item.SetBitmap(wx.BitmapFromImage(img))
        picMenu.AppendItem(item)
 
        # add menus to menubar
        menuBar.Append(carMenu, "&Veículos")
        menuBar.Append(picMenu, "&Imagens")
        self.SetMenuBar(menuBar)
 
    #----------------------------------------------------------------------
    def onExit(self, event):
        """"""
        self.Close()
 
#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm().Show()
    app.MainLoop()

Este exemplo é similar ao primeiro. A principal diferença é que nós adicionamos itens no lugar do menu File. Note que desta vez, especificamos nossos números ID explicitamente. Isso não é geralmente recomendado porque você pode terminar substituindo algum ID requerido pelo wx. Porém, você deve ter visto exemplos assim pela Internet. A próxima grande diferença não vem antes do picMenu. Aqui nós criamos um wx.MenuItem e adicionamos uma imagem a ele via wx.Image e o método SetBitmap do MenuItem. O resto é basicamente o mesmo.

Agora vamos investir algum tempo vendo como adicionar botões de marcar e selecionar (check e radio, respectivamente) ao nosso menu.

Adicionando Botões de Marcar e de Selecionar (Radio)

Tela demonstrando uso de radio e check boxes em menus com wxPython

Adicionar um botão de marcar ou selecionar ao seu menu é bastante simples. Vamos dar uma olhada em como isso é feito!

# coding: utf-8
# radiocheck.py
import wx
 
########################################################################
class MyForm(wx.Frame):
    """"""
 
    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title="Tutorial wx.Menu")
 
        self.panel = wx.Panel(self, wx.ID_ANY)
 
        # Create menu bar
        menuBar = wx.MenuBar()
 
        # Create radio menu
        radioMenu = wx.Menu()
        idleItem = radioMenu.Append(wx.NewId(), "IDLE",
                                   "um shell para Python feito em Tcl/Tk",
                                   wx.ITEM_RADIO)
        pyCrustItem = radioMenu.Append(wx.NewId(),"PyCrust",
                                      "um shell para Python feito em wxPython",
                                      wx.ITEM_RADIO)
        psiItem = radioMenu.Append(wx.NewId(), "psi",
                                  "um shell simples para Python feito em wxPython",
                                  wx.ITEM_RADIO)
        menuBar.Append(radioMenu, "&Radio")
 
        # create check menu
        checkMenu = wx.Menu()
        wgItem = checkMenu.Append(wx.NewId(), "Wells Fargo", "", wx.ITEM_CHECK)
        citiItem = checkMenu.Append(wx.NewId(), "Citibank", "", wx.ITEM_CHECK)
        geItem = checkMenu.Append(wx.NewId(), "GE Money Bank", "", wx.ITEM_CHECK)
        menuBar.Append(checkMenu, "&Check")
 
        # Attach menu bar to frame
        self.SetMenuBar(menuBar)
 
#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm().Show()
    app.MainLoop()

Sim, como você pode ver, tudo o que você precisa fazer é adicionar uma flag wx.ITEM_RADIO ou wx.ITEM_CHECK como um tipo de parâmetro, que é o quarto parâmetro. Por que é chamado de "tipo" ao invés de "estilo" como nos outros componentes visuais? Bem, enquanto discutia sobre isso no canal de IRC do wxPython, Robin Dunn (criador do wxPython) disse que provavelmente é assim por se tratarem de tipos de itens de menu diferentes.

Sub-Menus

Tela de exemplo do uso de submenus

A biblioteca wxPython suporta sub-menus. Aqui está um exemplo realmente simples que nos mostra como se faz iso.

# coding: utf-8
# submenu.py
import wx
 
########################################################################
class MyForm(wx.Frame):
    """"""
 
    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title="Tutorial wx.Menu")
 
        self.panel = wx.Panel(self, wx.ID_ANY)
 
        menuBar = wx.MenuBar()
        fileMenu = wx.Menu()
        openMenuItem = fileMenu.Append(wx.NewId(), "Abrir")
 
        # create a submenu
        subMenu = wx.Menu()
        historyMenuItem = subMenu.Append(wx.NewId(), "Mostrar Histórico")
        fileMenu.AppendMenu(wx.NewId(), "Histórico", subMenu)
 
        exitMenuItem = fileMenu.Append(wx.NewId(), "Sair",
                                       "Deixar a aplicação")
        menuBar.Append(fileMenu, "&Arquivo")
        self.Bind(wx.EVT_MENU, self.onExit, exitMenuItem)
        self.SetMenuBar(menuBar)
 
    #----------------------------------------------------------------------
    def onExit(self, event):
        """"""
        self.Close()
 
#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm().Show()
    app.MainLoop()

O segredo aqui é que ao invés de usarmos o método Append do filemenu, usamos o método AppendMenu. Como o novo sugere, ele permite ao programador acrescentar um menu ao invés de um item de menu. Yup, é isso aí!

Menus Flutuantes (ou Pop-up ou ContextMenus)

Tela de exemplo de uso dos menus flutuantes

Menus flutuantes são menus geralmente acessados através do botão direito do mouse em um navegador ou em um arquivo. Eles também são conhecidos como Menus de Contexto (ou menus pop-up). Aqui temos um exemplo bastante trivial para você estudar.

# coding: utf-8
# submenu.py
import wx
 
########################################################################
class MyForm(wx.Frame):
    """"""
 
    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title="Tutorial de Menu Flutuante")
 
        panel = wx.Panel(self, wx.ID_ANY)
 
        lbl = wx.StaticText(panel, label="Clique com o botão direito em qualquer lugar por aqui!")
        self.Bind(wx.EVT_CONTEXT_MENU, self.onContext)
 
    #----------------------------------------------------------------------
    def onContext(self, event):
        """
        Create and show a Context Menu
        """
 
        # only do this part the first time so the events are only bound once 
        if not hasattr(self, "popupID1"):
            self.popupID1 = wx.NewId()
            self.itemTwoId = wx.NewId()
            self.itemThreeId = wx.NewId()
            self.Bind(wx.EVT_MENU, self.onPopup, id=self.popupID1)
            self.Bind(wx.EVT_MENU, self.onPopup, id=self.itemTwoId)
            self.Bind(wx.EVT_MENU, self.onExit, id=self.itemThreeId)
 
        # build the menu
        menu = wx.Menu()
        itemOne = menu.Append(self.popupID1, "ItemUm")
        itemTwo = menu.Append(self.itemTwoId, "ItemDois")
        itemThree = menu.Append(self.itemThreeId, "Sair")
 
        # show the popup menu
        self.PopupMenu(menu)
        menu.Destroy()
 
    #----------------------------------------------------------------------
    def onExit(self, event):
        """
        Exit program
        """
        self.Close()
 
    #----------------------------------------------------------------------
    def onPopup(self, event):
        """
        Print the label of the menu item selected
        """
        itemId = event.GetId()
        menu = event.GetEventObject()
        menuItem = menu.FindItemById(itemId)
        print menuItem.GetLabel()
 
#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm().Show()
    app.MainLoop()

Para começar, ligamos wx.EVT_CONTEXT_MENU ao frame. Isso nos permite clicar com o botão direito em qualquer lugar e acionar o evento de menu de contexto, que criará e mostrará o menu flutuante. O código no método onContext é baseado no demo do wxPython para menus flutuantes. Como você pode ver, usamos uma checagem condicional, testando s o evento de menu já foi ativado. Se ele já foi ativado, não o será novamente. Em seguida, criamos nosso menu de um modo bem parecido com os anteriores. Finalmente, chamamos o método PopupMenu do frame e passamos para ele o nosso novo menu. Ele então mostra o menu ao usuário. Quando o usuário clica em um item do menu, o evento associado ao item será ativado e o menu será destruído.

Os primeiros dois itens do menu estão ligados ao método onPopup. Isso nos permite ver como podemos acessar o Menu e os atributos de um MenuItem. Você pode obter o id do menu com o evento e do Menu em si com o método GetEventObject do evento. Assim você pode usar o método FindItemById do menu para pegar um controlador para o item de menu propriamente. Finalmente, imprimimos a etiqueta do item de menu.

E pra terminar

Now you should know most of the menu methods and how to create them, bind events and make different kinds of menu items. You even know how to create popup menus! Now you can make your applications have fancy menus too.

Agora você já conhece grande parte dos métodos de menu e como criar menus, controlar eventos e fazer diferentes tipos de itens de menu. Você também sabe como criar menus flutuantes! Agora você pode fazer suas aplicações também terem menus originais.

Foto do post: Black Rat Snake, de cotinis.

Criando PDFs em Python com Reportlab

Se você não tem nada a ver com programação, nem tem interesse no assunto, simplesmente ignore este artigo.


Mike Driscoll tem um blog dedicado a Python chamado The Mouse vs. the Python e eventualmente há excelentes artigos por lá. Artigos estilo receita de bolo. Já traduzi um deles em outros tempos, falando sobre edição de registros do Windows: Editando o Registro do Windows em Python com o _winreg.

No final do ano passado, o Mike publicou um Top 10 de seus artigos. Aproveitei a lista e traduzi o artigo mais visitado de seu blog em 2011. Não é somente questão de popularidade, o artigo é muito bom e fala sobre como gerar arquivos PDF em Python: A Simple Step-by-Step Reportlab Tutorial.

Esta é uma tradução livre e modifiquei sutilmente algumas coisas, incluindo os exemplos. Agradeço ao Mike pelos excelentes artigos e me desculpo pelas liberdades que tomei na tradução (incluindo a mudança no nome do artigo). Vamos a ele!


O subtítulo deste artigo poderia facilmente ser "Como criar PDFs com Python", mas o Wordpress não suporta isso. De qualquer forma, a melhor biblioteca é a Reportlab.. Ela não é distribuída junto com a biblioteca padrão, de modo que você precisará baixá-la para poder executar com sucesso os exemplos deste tutorial. Você vai se deparar com pelo menos um exemplo de como colocar uma imagem no PDF, que quer dizer que você também precisará da Python Imaging Library (PIL). Pelo que entendi, Reportlab é compatível com Python 2.x, IronPython e Jython. Eles Eles estão trabalhando em um port para Python 3.x (ou estarão muito em breve)

Instalação

Reportlab suporta a maioria dos métodos de instalação em Python. Você tem a opção de baixar o código-fonte e rodar “python setup.py install” ou rodar um instalador de binário (em Windows). Havia uma discussão recente na lista de email que indicava que eles adicionariam suporte a pip também. A discussão que eu li sobre suporte do Reportlab ao easy_install é confusa, de modo que eu não estou certo se eles já dão suporte àquele método ou não. (Nota do Tradutor: em Trisquel ou outra distribuição GNU/Linux baseada em Debian, você pode instalar facilmente o Reportlab e o PIL com o comando "apt-get install python-reportlab python-imaging")

Criando um PDF simples

Reportlab tem uma documentação decente. O que eu quero dizer com isso é que a documentação nos dá aquilo de que precisamos para começar, mas quando você acha alguma coisa um tanto mais complexa para fazer, você tem correr com suas próprias pernas. Só recentemente eles adicionaram uma sessão Code Snippets ao site, que espero que venha a agrupar receitas, dicas e truques, de modo que melhore essa questão. Mas basta disso. Vamos ver como se cria alguma coisa.

No Reportlab, o componente de nível mais baixo que é usado regularmente é o objeto canvas do pacote pdfgen. As funções nesse pacote lhe permitem "pintar" um documento com seu texto, suas imagens, linhas ou o que você quiser. Eu

In Reportlab, the lowest-level component that’s used regularly is the canvas object from the pdfgen package. The functions in this package allow you to “paint” a document with your text, images, lines or whatever. Já ouvi algumas pessoas descreverem isso como escrever em Postscript. Eu tenho minhas dúvidas se isso é realmente tão ruim assim. Pela minha experiência, é bem parecido com você usar um toolkit para fazer interface gráfica em regiões específicas, com posicionamentos absolutos. Vejamos como o objeto canvas funciona:

from reportlab.pdfgen import canvas
 
c = canvas.Canvas("ola.pdf")
c.drawString(100,750,"Bem-vindo ao Reportlab!")
c.save()

Você terminará com um arquivo PDF parecido com isso:

PDF do exemplo, de Olá Mundo

A primeira coisa a se notar sobre esse código é que se quisermos salvar o PDF, precisamos fornecer um nome de arquivo ao objeto Canvas. O endereço para o arquivo pode ser um caminho tanto absoluto como relativo. Nesse exemplo, o PDF será criado no mesmo lugar onde você está quando chamar o script. A próxima peça do quebra-cabeças é o método drawString. Ele desenhará o texto do jeito que você mandar. Quando usamos o objeto canvas, ele começa no canto inferior esquerdo da página. Assim, para este exemplo, pedimos para desenhar o texto a 100 pontos da margem esquerda e a 750 pontos do canto inferior da página (1 ponto equivale a 1/72 polegada). Você pode mudar esse padrão no construtor do Canvas passando um zero ao parâmetro bottomup. Entretanto, eu não tenho muita certeza do que acontecerá se você fizer isso, já que o guia de usuário do Reportlab não é muito claro a esse respeito. A peça final do código que foi apresentado é a que salva o seu PDF.

Isso foi fácil! Você já criou um PDF simples! Note que o tamanho por padrão do Canvas já é A4, de modo que se você for estadunidense provavelmente desejará mudá-lo para o formato letter. É fácil fazer isso no Reportlab. Tudo o que você precisa fazer é o seguinte:

from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
 
canvas = canvas.Canvas('arquivo.pdf', pagesize=letter)
width, height = letter

A principal razão para pegar a largura e altura da página é que você pode definir margens, além de poder usá-las para fazer cálculos e decidir quando adicionar uma quebra de página. Vamos dar uma olhada por alto no construtor da classe Canvas para ver que opções nós temos mais:

def __init__(self,filename,
    pagesize=letter,
    bottomup = 1,
    pageCompression=0,
    encoding=rl_config.defaultEncoding,
    verbosity=0
    encrypt=None):

Esse código foi tirado diretamente do Guia de Usuário do Reportlab, página 11. Você pode ler sobre outras opções nesse guia se você quiser os detalhes completos.

Agora vamos fazer algo um pouco mais difícil e útil.

Um Pequeno Formulário, uma Pequena Função

Formulário em PDF

Neste exemplo, criaremos um formulário imprimível parcial. Até onde eu sei, o Reportlab não suporta aqueles formulários preenchíveis na tela, os que foram adicionados aos produtos Adobe no decorrer dos anos. De qualquer modo, vamos ao código!

from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
 
canvas = canvas.Canvas("form.pdf", pagesize=letter)
canvas.setLineWidth(.3)
canvas.setFont('Helvetica', 12)
 
canvas.drawString(30,750,'COMUNICADO OFICIAL')
canvas.drawString(30,735,'EMPRESAS ACME')
canvas.drawString(500,750,"12/12/2011")
canvas.line(480,747,580,747)
 
canvas.drawString(275,725,'SALDO DEVEDOR:')
canvas.drawString(500,725,"R$ 1.000,00")
canvas.line(378,723,580,723)
 
canvas.drawString(30,703,'RECEBIDO POR:')
canvas.line(130,700,580,700)
canvas.drawString(130,703,"JOHN DOE")
 
canvas.save()

Isso é baseado no recibo atual que eu criei no trabalho. A principal diferença entre este e o exemplo anterior é o uso do método canvas.line. Você pode usá-lo para desenhar linhas no seu documento passando pares X-Y. Eu usei esta funcionalidade para criar grades, embora isso seja um saco. Outros pontos interessantes nesse código incluem o comando setLineWidth(.3), que diz ao Reportlab quão grossas devem ser as linhas; e o comando setFont('Helvetica', 12), que nos permite especificar a fonte e tamanho.

Nosso próximo exemplo vai envolver o que aprendemos até agora e nos introduzirá nos fluidos.

Indo com o Fluxo

Se você é um publicitário ou faz algum tipo de trabalho com cartas, então Reportlab será um excelente acréscimo ao seu arsenal. Nós o usamos para criar cartas de formulário para pessoas com bilhetes de estacionamento vencidos. O exemplo a seguir é baseado em algum código que eu escrevi para essa aplicação, embora a carta seja um tanto diferente. (Note que o código abaixo não rodará se você não tiver a Python Imaging Library instalada).

# -*- coding: UTF-8 -*-
import time
from reportlab.lib.enums import TA_JUSTIFY
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import inch
 
doc = SimpleDocTemplate("form_letter.pdf",pagesize=letter,
                        rightMargin=72,leftMargin=72,
                        topMargin=72,bottomMargin=18)
Story=[]
logo = "python-logo.png"
magName = "Pythonista"
issueNum = 12
subPrice = "99.00"
limitedDate = "03/05/2010"
freeGift = "Bisão de pelúcia"
 
formatted_time = time.ctime()
full_name = "Mike Driscoll"
address_parts = ["411 State St.", "Marshalltown, IA 50158"]
 
im = Image(logo, 2*inch, 2*inch)
Story.append(im)
 
styles=getSampleStyleSheet()
styles.add(ParagraphStyle(name='Justify', alignment=TA_JUSTIFY))
ptext = '<font size=12>%s</font>' % formatted_time
 
Story.append(Paragraph(ptext, styles["Normal"]))
Story.append(Spacer(1, 12))
 
# Create return address
ptext = '<font size=12>%s</font>' % full_name
Story.append(Paragraph(ptext, styles["Normal"]))
for part in address_parts:
    ptext = '<font size=12>%s</font>' % part.strip()
    Story.append(Paragraph(ptext, styles["Normal"]))
 
Story.append(Spacer(1, 12))
ptext = '<font size=12>Caro(a) %s:</font>' % full_name.split()[0].strip()
Story.append(Paragraph(ptext, styles["Normal"]))
Story.append(Spacer(1, 12))
 
ptext = '<font size=12>Gostaríamos de recebê-lo na nossa base de assinantes da Revista %s! \
        Você receberá %s edições pelo excelente preço inicial de $%s. Por favor responda até\
        %s para começar a receber nossa publicação e ainda levar esse maravilhoso presente: %s.</font>' % (magName,
                                                                                                issueNum,
                                                                                                subPrice,
                                                                                                limitedDate,
                                                                                                freeGift)
Story.append(Paragraph(ptext, styles["Justify"]))
Story.append(Spacer(1, 12))
 
 
ptext = '<font size=12>Agradecemos muito e esperamos seu retorno para lhe servir.</font>'
Story.append(Paragraph(ptext, styles["Justify"]))
Story.append(Spacer(1, 12))
ptext = '<font size=12>Atenciosamente,</font>'
Story.append(Paragraph(ptext, styles["Normal"]))
Story.append(Spacer(1, 48))
ptext = '<font size=12>Ima Sucker</font>'
Story.append(Paragraph(ptext, styles["Normal"]))
Story.append(Spacer(1, 12))
doc.build(Story)

Bem, aqui teve muito mais código do que nos nossos exemplos anteriores. Precisaremos olhá-lo com calma para entendermos tudo o que está sendo feito. Quando você estiver pronto, simplesmente continue lendo. (N. T. Como traduzi o código do exemplo e o adaptei sutilmente, fez-se necessário o uso daquela primeira linha de comentário no código, que diz ao Python que o código a seguir está em Unicode. Se você salva seus arquivos em ISO-8859-1, basta colocar esse código no lugar de UTF-8 que está tudo bem).

A primeira parte que precisamos olhar são as novas linhas de importação:

from reportlab.lib.enums import TA_JUSTIFY
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import inch

De enums, importamos “TA_JUSTIFY”, que permite que nossas strings tenham formatação justified. Há várias outras constantes que podemos usar: alinhamento à direita, à esquerda e algumas outras coisas divertidas. Em seguida temos o módulo platypus (que vem de Page LAyout and TYPography Using Scripts. N. T.: platypus também significa "ornitorrinco"). Ele contem um monte de módulos, mas provavelmente os mais importantes deles são os fluidos, como o Paragraph. Um fluido tem tipicamente os seguintes atributos: wrap, draw e algumas vezes split. Eles são usados para escrever com facilidade parágrafos, tabelas e outras construções de múltiplas páginas.

A classe SimpleDocTemplate nos permite definir em só lugar margens, tamanho da página, nome do arquivo e uma pá de outras configurações para o nosso documento. Um "Spacer" é bom para adicionar uma linha em branco, como uma quebra de parágrafo. A classe Image utiliza a Python Image Library para nos permitir inserir e manipular facilmente uma imagem no nosso PDF.

O getSampleStyleSheet pega um conjunto de estilos padrão que podemos usar no nosso PDF.  ParagraphStyle é usado para definir o alinhamento do nosso parágrafo nesse exemplo, mas pode fazer muito mais do que isso (veja a página 67 do guia de usuário). Pra terminar, inch (polegada) é uma unidade de medida para ajudar no posicionamento de itens no seu PDF. Você pode vê-lo em ação quando nós posicionamos o logo: Image(logo, 2*inch, 2*inch). Isso quer dizer que o logotipo estará a duas polegadas do topo e a duas polegadas da esquerda.

Não recordo a razão para que os exemplos do Reportlab usem uma lista Story, mas é como nós faremos aqui também. Basicamente você cria uma linha de texto, uma tabela e imagem ou o que você quiser e as anexa à Story list. Você verá isso por todo o nosso exemplo. A primeira vez que fizemos isso foi quando adicionamos a imagem. Antes de prosseguir, precisamos olhar como adicionamos um estilo ao nosso objeto de estilos.

styles.add(ParagraphStyle(name='Justify', alignment=TA_JUSTIFY))

A razão para isso é importante e é para que você possa utilizar a lista de estilo para vários parágrafos de texto do seu documento. No código anterior, criamos um estilo de parágrafo chamado "Justify". Tudo o que ele faz é justificar nosso texto. Você verá um exemplo disso depois no texto. Por ora, vamos ver um exemplo rápido

ptext = '<font size=12>%s</font>' % formatted_time
Story.append(Paragraph(ptext, styles["Normal"]))

Para a nossa primeira linha de texto, usamos a classe Paragraph. Como você pode ver, a classe Paragraph aceita algumas tags estilo HTML. Aqui nós definimos o tamanho da fonte para 12 e usamos o estilo normal (que é alinhado à esquerda, entre outras coisas). O resto do exemplo é basicamente a mesma coisa, só que com espaçadores (Spacers) colocados aqui e ali. No fim, nós chamamos doc.build para criar o documento.

Resumindo

Agora você sabe o básico sobre criação de PDFs em Python usando Reportlab. Nós nem sequer arranhamos a superfície daquilo tudo que podemos fazer com Reportlab. Alguns exemplos incluem tabelas, gráficos, paginação, sobreposição de cores, links, gráficos e muito mais. Eu recomendo bastante que você baixe o módulo junto com o guia de usuário e mande ver!

Conheça o Ren'Py

Visual Novel é um tipo de jogo de videogame baseado em diálogo, como uma história interativa. São histórias que o jogador acompanha (geralmente lendo e vendo imagens associadas), sendo responsável por decidir que rumo a história tomará em alguns momentos.

Ren'Py é um software livre para criar jogos desse tipo. Feito em Python, como o nome sugere, ele cria a estrutura para uma Visual Novel, sendo capaz de gerar executáveis para Windows, Mac OS X, GNU/Linux e Android.

O código-fonte do jogo é escrito em uma sintaxe Python-like, facilmente carregando elementos de arquivos externos, como imagens e sons.

Os recursos que o Ren'Py oferecem incluem:

  • Menu principal que dá opções de iniciar o jogo, continuar um jogo salvo e ajustar configurações
  • Um menu de jogo durante o jogo propriamente, permitindo abrir um jogo salvo, salvar e ajustar configurações
  • Salvamento automático
  • O jogador pode retornar para telas anteriores, mudando sua decisão
  • Predição de imagens a serem carregadas, fazendo com que as imagens sejam carregadas em segundo plano, evitando que o usuário tenha que se deparar com momentos de "Loading"
  • Permite controlar o jogo usando mouse, teclado ou joystick
  • Permite escolher se o jogo funcionará em tela cheia ou dentro de uma janela
  • Auto-avanço de texto sem ter que usar o teclado, com ajuste baseado na quantidade de texto mostrada por tela
  • Pode ocultar textos para que o usuário veja a imagem que está trás
  • Habilidade de mudar música, efeito sonoro e volume de voz.
  • Facilidade de personalização e localização (tradução)
  • Permite vários efeitos de transição de cena/imagem
  • Permite que se expanda suas funcionalidades através de código-fonte em Python

É um excelente software livre, que pode ser baixado do site http://www.renpy.org/

Editando o Registro do Windows em Python com o _winreg

Primeiramente, um alerta aos leitores do blog: este artigo a seguir é um artigo de programação. Fala sobre recursos da linguagem de programação Python. Se você não é programador, nem gosta dessas coisas, pode continuar visitando o blog (tá acompanhando Warning Zone?), apenas pule este post, que foi traduzido do artigo de Mike Driscoll, do blog Mouse vs. Python


A biblioteca padrão de Python é conhecida por incluir vários módulos e pacotes práticos, que podem ser usados sem necessidade de instalar nada mais. Esta é uma das principais razões de a bibliotca padrão ser frequentemente referenciada como "baterias incluídas". Assim, não deve ser surpresa o fato de o Python incluir um módulo só para Windows, que permita editar o Registro do Windows. Esse módulo em particular recebe o estranho nome de _winreg (estranho devido ao sublinhado no início). Neste artigo, aprenderemos como começar a trabalhar com o Registro usando essa bateria.

Lendo o Registro

Usar o Python para ler dados a partir do registro é muito fácil. No exemplo a seguir, procuraremos pelo caminho onde o Outlook Express está instalado:

from _winreg import *
key = OpenKey(HKEY_LOCAL_MACHINE, r'Software\Microsoft\Outlook Express', 0, KEY_ALL_ACCESS)
QueryValueEx(key, "InstallRoot")

Na minha máquina, isso retorna a seguinte tupla: (u’%ProgramFiles%\\Outlook Express’, 2). A tupla combina o valor do registro com o tipo de valor. Há dois outros métodos de consulta que podem ser chamados: QueryInfoKey e QueryValue. O primeiro lhe dá informações internas sobre a chave em si, na forma de três inteiros; enquanto o último recupera apenas o dado para o primeiro valor da chave que tenha nome NULL. A documentação recomenda que você use QueryValueEx sempre que possível.

Devemos explicar rapidamente o que está acontecendo no código anterior. A função OpenKey recebe uma constante HKEY*, uma string de caminho da subchave, um inteiro reservado (que precisa ser igual a zero) e a máscara de segurança. Neste caso, passamos KEY_ALL_ACCESS, que nos dá controle total daquela chave. Como tudo o que fizemos foi ler a chave, provavelmente deveríamos ter utilizado KEY_READ ao invés da outra constante. Já quanto ao QueryValueEx, ele recebe somente o objeto chave e o nome do campo que queremos consultar.

Escrevendo no Registro

Se você andou lendo o blog do Mike ultimamente, provavelmente já viu o módulo _winreg sendo utilizado para escrita no registro. Isso será apenas revisto por você, assim fique à vontade para pular esta sessão. Começaremos com um exemplo prático. No código a seguir, vamos definir a página inicial do Internet Explorer. Como sempre, favor notar que a edição de entradas no Registro pode ser muito perigosa. Esteja certo de ter feito backup do seu registro antes de tentar editá-lo. Agora, que comece o espetáculo!

keyVal = r'Software\Microsoft\Internet Explorer\Main'
try:
    key = OpenKey(HKEY_CURRENT_USER, keyVal, 0, KEY_ALL_ACCESS)
except:
    key = CreateKey(HKEY_CURRENT_USER, keyVal)
SetValueEx(key, "Start Page", 0, REG_SZ, "http://bardo.ws/")
CloseKey(key)

No código acima, tentamos abrir a seguinte chave: HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main e definir o valor “Start Page” para este blog. Se a abertura falha, isso geralmente é devido ao fato de a chave não existir, assim tentamos criá-la no nosso manipulador de exceção. Então usamos SetValueEx para definir o valor e, como todo bom programador, nós fechamos a chave a partir do momento em que não precisaremos mais manuseá-la. Se você pulou o comando CloseKey, o fato de o programa ser feito em Python fará com que o Python o feche para você. Porém, se você continuar trabalhando nesta chave, você pode ter uma violação de acesso ao tentar abrí-la com ela já aberta. Assim, a lição que fica é que sempre feche uma chave quando terminar de mexer nela.

Outros Métodos do _winreg

Há vários outros métodos na biblioteca _winreg além dos que foram mostrados. O método DeleteKey é prático quando você precisa remover uma chave. Infelizmente, tenho passado por ocasiões em que preciso remover chaves recursivamente, como acontece numa desinstalação, e o _winreg ainda não tem uma forma embutida de fazer isso. Você pode escrever o seu próprio, é verdade, ou pode baixar um wrapper que faça isso por você, como o YARW (Yet Another Registry Wrapper).

DeleteValue é similar ao DeleteKey, exceto que você apaga apenas um valor. Sim, isso é bem óbvio. Se você quer escrever seu próprio código de eliminação recursiva, provavelmente vai querer dar uma olhada na forma como EnumKey e EnumValue enumeram as chaves e valores, respectivamente. Vamos ver então como usar o EnumKey:

from _winreg import EnumKey, HKEY_USERS
 
try:
    i = 0
    while True:
        subkey = EnumKey(HKEY_USERS, i)
        print subkey
        i += 1
except WindowsError:
    # WindowsError: [Errno 259] No more data is available    
    pass

O código acima irá percorrer todo o HKEY_USERS, imprimindo as subchaves na saída padrão até que termine e um WindowsError seja gerado. Realmente este código não desce para as subchaves, mas deixarei essa tarefa como um exercício para o leitor que quiser praticar.

O último método de que iremos falar aqui é o ConnectRegistry. Ele é útil quando nós precisamos editar o Registro de uma máquina remota. Ele só aceita dois argumentos: o nome do computador e a chave à qual se conectar (por exemplo, HKEY_LOCAL_MACHINE). Note que quando conectamos máquinas remotas, nós só podemos editar certas chaves, enquanto outras estão indisponíveis.

Encerrando

Espero que este artigo tenha sido útil para você e tenha lhe dado um montão de ideias para projetos futuros. Eu tenho muitos scripts de login que usam essa maravilhosa biblioteca, e um par que usa o YARW. Tem sido muito útil até agora e eu espero que também seja para você.

Leia Também

Aprendendo por Exemplo

Aprender a programar envolve também leitura. Leitura de código-fonte. É muito útil quando sabemos exatamente o que querermos, mas enfrentamos dificuldades, podermos consultar códigos de terceiros para coisas similares. Foi o que aconteceu hoje com o código para fazer a barra de progresso do Redutor funcionar corretamente.

Felizmente existem sistemas de busca próprios para código-fonte, que podem ser bem úteis. Atenção, hein! A utilidade que estou propondo é aprendizado e tira-dúvidas, não é copiar e colar para entregar como trabalho de faculdade...

Conheço duas ferramentas desse tipo, mas devem haver outras espalhadas por aí...

PortablePython

PortablePython

Outra vantagem do Python em relação a outras linguagens de scripts é a existência do Portable Python.

Você conhece PortableApps? É uma forma de rodar programas no Windows a partir do pendrive, sem precisar instalar nada. Muito útil se você, por exemplo, é cliente freqüente de lan house. Você pode ter o Firefox, o Thunderbird, o VLC e até mesmo o OpenOffice.org rodando a partir do seu pendrive, sem precisar de acesso como administrador às máquinas e sem incomodar ninguém.

A lista de programas que funcionam dessa forma é enorme. Dentre eles, está o Portable Python. Todo o ambiente Python: o interpretador e até mesmo o editor Scite. Vale a pena, viu? (ainda não sou usuário freqüente de lanhouses, mas gostei de saber desse projeto)

Claro que você pode utilizar o Portable Python sozinho, mas se você instalar o PortableApps, fica mais interessante, já que ganha um menu. Neste caso, descompacte o Portable Python para a pasta PortableApps no dispositivo com PortablApps já instalado.

Páginas