Criação de Aplicação em Python com Kivy
Framework Kivy
[editar | editar código]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]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]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]
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]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.