Criação de Aplicação em Python com Kivy

Fonte: Wikiversidade

Framework Kivy[editar | editar código-fonte]

Kivy é uma framework open-source para desenvolvimento de aplicações com interface gráfica em Python[1]. Escrita em Python, foi lançada em 2011 e é compatível com iOS, Android, macOS, Windows, Linux, entre outros[2].

Instalando Kivy[editar | editar código-fonte]

Para instalar Kivy em sua máquina, é necessário que ela já tenha Python e pip instalados. Assim, basta executar o comando:

pip install kivy

Para mais informações, visite o guia de instalação na documentação oficial do Kivy[3].

Construindo uma Calculadora[editar | editar código-fonte]

Nesse tutorial criaremos uma calculadora para demonstrar o básico das capacidades do kivy.

main.py - A Base da Aplicação[editar | editar código-fonte]

Começamos o projeto por criar um arquivo main.py que será a base para a nossa aplicação, e importando as classes Kivy necessárias:

from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window
from kivy.app import App

O Kivy funciona com base em uma árvore de widgets (cada um podendo conter outros widgets), sendo eles objetos da ui da aplicação.

BoxLayout que incluímos é um tipo de widget responsável por organizar seus widgets filhos como uma caixa (mais a frente veremos como personalizar essa organização).

Agora que incluímos o necessário para criar a aplicação precisamos de uma classe para ela e para o widget raiz dela (utilizaremos uma classe que herda de BoxLayout). Também podemos colocar entre os atributos da classe do aplicativo as cores que utilizaremos na ui (em rgba) para facilitar a leitura do código Kivy.

class Calculator(BoxLayout):
    pass
    
class CalculatorApp(App):
    color_background = (97/255 , 97/255 , 104/255, 1)
    color_button     = (254/255, 254/255, 254/255, 1)
    color_press      = (49/255 , 159/255, 255/255, 1)
    color_equals     = (255/255, 145/255, 49/255 , 1)
    color_textbox    = (207/255, 212/255, 225/255, 1)
    color_text       = (55/255 , 52/255 , 52/255 , 1)
    
    def build(self):
        return Calculator()

A função build que definimos server para construir a árvore da aplicação, utilizando então um widget do tipo Calculator como raiz.

Por último em nosso código base, podemos rodar a aplicação e personalizar o tamanho da janela a ser criada.

if __name__ == '__main__':
    Window.size = (400, 600)
    CalculatorApp().run()

Caso executemos a aplicação agora, teremos apenas uma tela preta, já que precisamos definir a nossa aplicação em um arquivo kv, então vamos criar calculator.kv para fazer isso.

calculator.kv - O Layout da Aplicação[editar | editar código-fonte]

Nesse novo arquivo, começamos por indicar a versão do Kivy que estamos trabalhando, com o seguinte header:

#:kivy 1.0.9

Podemos então descrever nosso widget Calculator, lembrando que ele é uma classe que herda de BoxLayout, logo, com suas propriedades conseguimos dizer que seus widgets filhos serão organizados na orientação vertical (posicionados em fila de cima para baixo). Também mudaremos o background da raiz desenhando um retângulo com a cor desejada em sua posição da seguinte forma:

<Calculator>:
    orientation: 'vertical'
    memory: ""
    canvas.before:
        Color:
            rgba: app.color_background
        Rectangle:
            pos: self.pos
            size: self.size

Definimos o atributo memory para armazenar os valores a serem calculados posteriormente e utilizamos app.color_background para acessar a variável de cor que definimos na classe do aplicativo.

Criaremos agora seus primeiros filhos, a área da tela (mais um BoxLayout) onde teremos a memória e resultados da calculadora, e a área dos botões (GridLayout de 4x4 espaços).

Para organizar melhor seus tamanhos, fazendo o display da calculadora ocupar 20% e os botões 80% do espaço vertical, podemos utilizar o atributo size_hint e definir seu tamanho com base no de seu pai, de forma que:

size_hint[0]: 0,5 é a mesma coisa que size[0]: self.parent.size[0]*0,5 (o mesmo vale para size_hint[1]).

<Calculator>:
...
    BoxLayout:
        size_hint: 1, 0.2
        canvas.before:
            Color:
                rgba: app.color_textbox
            RoundedRectangle:
                pos: self.pos[0]+5, self.pos[1]+5 # centraliza o retângulo no widget
                size: self.size[0]-10, self.size[1]-10
                radius: [10,10,10,10]
    GridLayout:
        size_hint: 1, 0.8
        cols: 4 # define o layout como uma rede 4x4

O RoundedRectangle definido no canvas do BoxLayout é outra forma que podemos desenhar, nesse caso para representar o leitor utilizaremos um retângulo arredondado que seja levemente menor que o tamanho de BoxLayout.

Com os layouts definidos podemos então adicionar o widget de texto (Label) em BoxLayout para que o display possa mostrar o que estamos calculando. Daremos um id à essa Label para que possamos editar seu texto depois.

<Calculator>:
...
    BoxLayout:
    ...
        Label:
            id: result_label
            halign: 'right' # alinha o texto à direita
            valign: 'center' # alinha o texto ao centro do eixo y
            padding: [15,0] # distancia levemente o texto da borda
            text_size: self.size
            font_size: 50
            text: ''
            color: app.color_text

Agora podemos então definir os botões da calculadora, para isso criaremos uma classe no fim do próprio aquivo kv, que herda de Button, para termos a mesma configuração para todos botões sem ser necessário repetir o código.

<CalculatorButton@Button>:
    # deixamos o botão invisível para desenhar no lugar dele um retângulo arredondado
    background_color: (0,0,0,0)
    canvas.before:
        Color:
            # self.state diz se o botão está pressionado ou não
            rgb: app.color_button if self.state == 'normal' else app.color_press
        RoundedRectangle:
            pos: self.pos[0]+5, self.pos[1]+5
            size: self.size[0]-10, self.size[1]-10
            radius: [10,10,10,10]
    color: app.color_text # cor da fonte do texto do botão
    font_size: 25

Com a classe criada podemos instanciar os botões no GridLayout:

<Calculator>:
...
    GridLayout:
    ...
        CalculatorButton:
            text: '7'
        CalculatorButton:
            text: '8'
        CalculatorButton:
            text: '9'
        CalculatorButton:
            text: 'C'
        CalculatorButton:
            text: '4'
        CalculatorButton:
            text: '5'
        CalculatorButton:
            text: '6'
        CalculatorButton:
            text: '+'
        CalculatorButton:
            text: '1'
        CalculatorButton:
            text: '2'
        CalculatorButton:
            text: '3'
        CalculatorButton:
            text: '-'
        CalculatorButton:
            text: '0'
        CalculatorButton:
            text: '*'
        CalculatorButton:
            text: '/'
        CalculatorButton:
            text: '='

Podemos alterar a cor do botão '=' definindo um novo fundo para ele, sobrescrevendo a nossa classe CalculatorButton:

<Calculator>:
...
    GridLayout:
    ...
        CalculatorButton:
            text: '='
            canvas.before:
                Color:
                    rgb: app.color_equals if self.state == 'normal' else app.color_press
                RoundedRectangle:
                    pos: self.pos[0]+5, self.pos[1]+5
                    size: self.size[0]-10, self.size[1]-10
                    radius: [10,10,10,10]

Nossa ui da calculadora está pronta, porém os botões ainda não fazem nada. Para corrigir isso, definiremos a função que será chamada quando cada botão é pressionado. Essa função será chamada de input, e será criada na classe Calculator no lugar do pass que colocamos antes:

<CalculatorButton@Button>:
    on_press: root.parent.parent.input(self.text) # self.text é o caractere do botão
    ...

Lembrando que o pai de cada botão é GridLayout, e seu pai é Calculator, que possui a função input, definida no arquivo main.py:

class Calculator(BoxLayout):
    def input(self, value): # value é o caractere do botão que chamou a função
        if value == 'C':
            self.memory = '' # limpa a memória
            self.ids.result_label.text = self.memory # limpa o display
        elif value == '=':
            try:
                result = eval(self.memory) # tenta efetuar o cálculo da memória
                if type(result) == int:
                    self.memory = str(result)
                else:
                    self.memory = f"{result:.7}"
                self.ids.result_label.text = self.memory # mostra o resultado no display
            except:
                self.ids.result_label.text = "Error" # mostra erro no display
                self.memory = ''
        else:
            self.memory += value # coloca o caractere do botão na memória 
            self.ids.result_label.text = self.memory # mostra a memória no display

Por fim podemos executar a aplicação com o comando python main.py e utilizar a calculadora.

Referências[editar | editar código-fonte]

  1. https://kivy.org/index.html
  2. https://en.wikipedia.org/wiki/Kivy_(framework)
  3. https://kivy.org/doc/stable/gettingstarted/installation.html