Widgets, propriedades e eventos
Vimos no primeiro artigo dessa série que um aplicativo Python com Flet consiste em código Python para a realização da lógica do aplicativo, usando o Flet como camada de exibição. Mais tarde nos preocuparemos em fazer uma separação explícita das camadas. Por enquanto basta notar que o Flet cria uma árvore de widgets cujas propriedades são controladas pelo código. Widgets também podem estar associados à ações ligadas a funções. Portanto, para construir aplicativos com Flet, precisamos conhecer esses widgets, suas propriedades e eventos que respondem.
Alguns controles tem a função principal de obter informações do usuário, como botões, menus dropdown ou caixas de texto, para inserção de dados. Outros servem para a exibição de informações calculadas pelo código, mostrando gráficos, figuras ou textos. As caixas de textos podem ser usadas em ambos os casos.
A interface do Flet é montada como uma composição de controles, arranjados em uma hierarquia sob forma de árvore que se inicia com uma Page. Dentro dela são dispostos os demais controles, sendo que alguns deles são também conteineres, abrigando outros controles. Todos os controles, portanto, possuem um pai, exceto a Page. Controles como Column, Row e Dropdown podem conter controles filhos, como mostrado na figura 10.
Categorias de Controles
🔘 Controles | Categoria | Itens |
---|---|---|
🔘 Layout | diagramação | 16 itens |
🔘 Navigation | navegação | 3 itens |
🔘 Information Displays | exibição de informação | 8 itens |
🔘 Buttons | botões | 8 itens |
🔘 Input and Selections | entrada e seleções | 6 itens |
🔘 Dialogs, Alerts, Panels | dialogo e paineis | 4 itens |
🔘 Charts | gráficos | 5 itens |
🔘 Animations | animações | 1 item |
🔘 Utility | utilidades | 13 itens |
Propriedades comuns a vários controles
Algumas propriedades são comuns a todos (ou quase todos) os controles. Vamos primeiro listá-las e depois apresentar alguns exemplos de uso. As propriedades marcadas com o sinal ≜ só são válidas quando estão dentro de uma controle Stack, que será descrito após a tabela.
bottom |
≜ | Distância entre a borda inferior do filho e a borda inferior do Stack. |
data |
Um campo auxiliar de dados arbitrários que podem ser armazenados junto a um controle. | |
disabled |
Desabilitação do controle. Por padrão disabled = False . Um controle desabilitado fica sombreado e não reage a nenhum evento. Todos os filhos de um controle desabilitado ficam desabilitados. |
|
expand |
Um controle dentro de uma coluna ou linha pode ser expandido para preencher o espaço disponível. expand=valor , onde valor pode ser booleano ou inteiro, um fator de expansão, usado para dividir o espaço entre vários controles. |
|
hight |
Altura do controle, em pixeis. | |
left |
≜ | Distância da borda esquerda do filho à borda esquerda do Stack. |
right |
≜ | Distância da borda direita do filho à borda direita do Stack. |
top |
≜ | Distância da borda superior do filho ao topo do Stack. |
visible |
Visibilidade do controle e seus filhos. vivible = True por padrão. Controles invisíveis não recebem foco, não podem ser selecionados nem respondem a eventos. |
|
widht |
Largura de controle em pixeis. |
Um Stack é um controle usado para posicionar controles em cima de outros (empilhados). Veremos mais sobre ele na seção sobre layouts.
Transformações (Transformations)
Transformações são operações realizadas sobre os controles
offset |
É uma translação aplicada sobre um controle, antes que ele seja renderizado. A translação é dada em uma escala relativa ao tamanho do controle. Um deslocamento de 0,25 realizará uma translação horizontal de 1/4 da largura do controle. Ex,: ft.Container(..., offset=ft.transform.Offset(-1, -1) . |
opacity |
Torna o controle parcialmente transparente. O default é opacity=1.0 , nenhuma transparência. Se opacity=0.0 controle é 100% transparente. |
rotate |
Aplica uma rotação no controle em torno de seu centro. O parâmetro rotate pode receber um número, que é interpretado com o ângulo, em radianos, de rotação anti-horária. A rotação também pode ser especificada por meio de transform.Rotate, que permite estabelecer ângulo, alinhamento e posição de centro de rotação. Ex,: ft.Image(..., rotate=Rotate(angle=0.25 * pi, alignment=ft.alignment.center_left) representa uma rotação de 45° (π/4). |
scale |
Controla a escala ao longo do plano 2D. O fator de escala padrão é 1,0. Por ex.: ft.Image(..., scale=Scale(scale_x=2, scale_y=0.5) multiplica as dimensões em x por 2 e em y por .5. Alternativamente Scale(scale=3) multiplica por 3 nas duas direções. |
Exemplo de uso das Propriedades e Transformações
import flet as ft def main(page: ft.Page): def mover_x(e): ct.left += 20 page.update() def mover_y(e): ct.top += 20 page.update() def mover(e): bt3.value += .2 ct.offset=ft.transform.Offset(bt3.value, bt3.value) page.update() def sumir(e): ct.visible = not ct.visible page.update() def rodar(e): bt5.value+=.5 ct.rotate=ft.Rotate(angle=bt5.value, alignment=ft.alignment.center) page.update() def opaco(e): ct.opacity -= .1 page.update() def zerar(e): bt3.value=0 bt5.value=0 ct.left=0 ct.top=0 ct.offset=ft.transform.Offset(0, 0) ct.opacity = 1 ct.visible = True ct.rotate=ft.Rotate(angle=0, alignment=ft.alignment.center) page.update() bt1 = ft.ElevatedButton(" ", icon="arrow_circle_right", on_click= mover_x, width=50) bt2 = ft.ElevatedButton(" ", icon="arrow_circle_down", on_click= mover_y, width=50) bt3 = ft.ElevatedButton(" ", icon="SUBDIRECTORY_ARROW_RIGHT", on_click= mover, width=50) bt3.value=0 bt4 = ft.ElevatedButton("on/off", on_click= sumir, width=150) bt5 = ft.ElevatedButton("Rodar", on_click= rodar, width=150) bt5.value=0 bt6 = ft.ElevatedButton("Opaco", on_click= opaco, width=150) bt7 = ft.ElevatedButton("Zerar", on_click= zerar, width=150) ct = ft.Container(bgcolor="red", width=50, height=50, left=0, top=0, offset=ft.transform.Offset(0, 0)) page.add(ft.Row([bt1, bt2, bt3, bt4, bt5, bt6, bt7]), ft.Stack([ct], width=1000, height=1000)) ft.app(target=main)
Os botões executam as funções:
- bt1 ⇾ move para a direita, horizontalmente (ct.left += 20),
- bt2 ⇾ move para baixo, na vertical (ct.top += 20),
- bt3 ⇾ aumenta offset, nas duas direções (ct.offset=ft.transform.Offset(bt3.value, bt3.value)),
- bt4 ⇾ torna a imagem invisível/visível (ct.visible = not ct.visible),
- bt5 ⇾ gira imagem, anti-horário:
ct.rotate=ft.Rotate(angle=bt5.value, alignment=ft.alignment.center), - bt6 ⇾ torna a cor mais translúcida (ct.opacity -= .1),
- bt7 ⇾ retorna a imagem para o estado inicial,
onde ct = ft.Container, é o container de cor vermelha, mostrado no figura 12.
Atalhos de Teclado
Qualquer pessoa que faz uso intensivo do computador sabe da importância dos Atalhos de Teclado (Keyboard shortcuts). A possibilidade de não mover a mão do teclado para acionar o mouse pode significar melhor usabilidade e aumento de produtividade. Para isso o Flet oferece para o programador a possibilidade de inserir atalhos em seus aplicativos para que seu usuário possa dinamizar seu uso.
Para capturar eventos produzidos pelo teclado o objeto page implementa o método on_keyboard_event, que gerencia o pressionamento de teclas de caracter, em combinação com teclas de controle. Esse evento passa o parâmetro eque é uma instância da classe KeyboardEvent, e tem as seguintes propriedades:
e.key |
Representação textual da tecla pressionada. Veja nota†. |
e.shift |
Booleano: True se a tecla “Shift” foi pressionada. |
e.ctrl |
Booleano: True se a tecla “Control” foi pressionada. |
e.alt |
Booleano: True se a tecla “Alt” foi pressionada. |
e.meta |
Booleano: True se a tecla “Meta” foi pressionada††. |
Nota†: Além dos caracteres A … Z (todos apresentados em maiúsculas) também são representadas as teclas Enter, Backspace, F1 … F12, Escape, Insert … Page Down, Pause, etc. Alguns teclados permitem a reconfiguração de teclas, por exemplo fazendo F1 = Help, etc.
Nota††: A tecla Meta é representada em geral no Windows como tecla Windows e no Mac como tecla Command.
O seguinte código ilustra esse uso. A linha page.on_keyboard_event = on_teclado
faz com que eventos de teclado acionem a função on_teclado. O objeto e leva as propriedades booleanas e.ctrl, e.alt, e.shift, e.meta e o texto e.key.
import flet as ft def main(page: ft.Page): class BtControle(ft.TextField): def __init__(self, text): super().__init__() self.value = text self.width=100 self.text_size=25 self.bgcolor="blue" self.color="white" self.visible = False def on_teclado(e: ft.KeyboardEvent): c_ctrl.visible = e.ctrl c_alt.visible = e.alt c_shift.visible = e.shift c_meta.visible = e.meta c_key.visible = True c_key.value = e.key page.update() page.on_keyboard_event = on_teclado t1= ft.Text("Pressione qualquer tecla, combinada com \nCTRL, ALT, SHIFT ou META", size=25) c_ctrl = BtControle("Ctrl") c_alt = BtControle("Alt") c_shift = BtControle("Shift") c_meta = BtControle("Meta") c_key = BtControle("") page.add(t1) page.add(ft.Row(controls=[c_ctrl, c_alt, c_shift, c_meta, c_key])) ft.app(target=main)
O resultado desse código, quando executado e após o pressionamento simultaneo das teclas CTRL-ALT-SHIFT-J, está mostrado na figura 13.
O exemplo acima ilustra ainda uma característica da POO (programação orientada a objetos). Como temos que criar 5 caixas de texto iguais, exceto pelo seu valor, criamos uma classe BtControle (herdando de ft.TextField) e criamos cada botão como instância dessa classe. No código manipulamos a visibilidade desses botões.
Bibiografia
- Real Python:Python Classes: The Power of Object-Oriented Programming
- Real Python:Supercharge Your Classes With Python super()
- Python com Flet: Bibiografia Geral