Flet: Stack

Objeto Stack

Em alguns casos queremos colocar controles em cima de outros. No Flet é possível sobrepor vários filhos do controle Stack. Podemos, por exemplo, colocar um texto sobre uma imagem ou um container móvel, como fizemos no exemplo 3.

Propriedades de Stack

O controle Stack possui apenas 2 propriedades:

clip_behavior
Como será cortado (clipped) o conteúdo do objeto.
Os valores possíveis estão armazenados em no enum ClipBehavior com os valores:

  • NONE
  • ANTI_ALIAS
  • ANTI_ALIAS_WITH_SAVE_LAYER
  • HARD_EDGE (default)

controls
Uma lista contendo os controles a serem exibidos dentro de Stack, em ordem de exibição, sendo o último controle exibido por cima dos demais.

Controles dentro de Stack

Diversos controles, ao serem colocados dentro de um Stack passam a admitir propriedades de posição. São elas:

Figura 1: distâncias em Stack

left: distância entre a borda esquerda do controle filho até a borda esquerda do Stack.
right: distância entre a borda direita do controle filho até a borda direita do Stack.
bottom: distância entre a borda inferior do controle filho até a borda inferior do Stack.
top: distância entre a borda superior do controle filho até a borda superior do Stack.

Exemplo de uso do Stack

O exemplo de código a seguir insere 3 controles dentro de um Stack, 1 imagem e 2 linhas. Nessa posição eles admitem as propriedades listadas acima, em particular top e left que são usadas para mover a linha de texto.

1  import flet as ft
2  import time
3  
4  def main(page: ft.Page):
5      def voltar(e):
6          texto.size = 50
7          linha_texto.top=500
8          linha_texto.left=0
9          page.update()
10 
11     def partir(e):
12         while linha_texto.top > 0:
13             time.sleep(.1)
14             texto.size -= 1
15             linha_texto.top-=10
16             linha_texto.left+=10
17             page.update()
18 
19     imagem = ft.Image(src=f"https://phylos.net/wp-content/uploads/2020/02/deepfield.jpg",
20                       width=950, height=556, fit=ft.ImageFit.NONE)
21    
22     texto = ft.Text("Em uma galáxia muito muito distante...",
23                      color="yellow", size=50, weight="bold", opacity=0.3)
24   
25     linha_texto = ft.Row([texto], left = 0, top=500)
26
27     bt_partir = ft.ElevatedButton("Partir!", bgcolor="blue", color="white",
28                                   width=120, height= 35, on_click=partir)
29
30     bt_voltar = ft.ElevatedButton("Voltar", bgcolor="blue", color="white",
31                                    width=120, height= 35, on_click=voltar)
32
33     linha_botoes = ft.Row([bt_partir,bt_voltar], left = 10, top=10)
34
35     page.add(ft.Stack([imagem, linha_texto,linha_botoes], width=950, height=556))
36 
37 ft.app(target=main)
Figura 2: resultado do código com Stack. Apenas 3 frames são mostrados.

Um clique no botão Voltar retorna as propriedades do texto e da linha que o contém para seus valores iniciais. Observe que, se o botão Partir! for acionado antes que o loop na linha 12 tenha terminado a velocidade de subida do texto aumentará pois os incrementos serão aumentados (loops dentro de loops).

Exemplo: sobreposição de controles

Mais um exemplo ajudará a mostrar que, dentro de um Stack, controles desenhados estão dispostos em camadas. Se dois controles são posicionados no mesmo lugar o último deles, na camada superior, ficará visível, cobrindo o controle por baixo.

1  import flet as ft
2  
3  class Ct(ft.Container):
4      def __init__(self, cor, acima, direita, abaixo, esquerda):
5          super().__init__()
6          self.width=20
7          self.height=20
8          self.border_radius=5
9          self.bgcolor=cor
10         self.top=acima
11         self.right=direita
12         self.bottom=abaixo
13         self.left=esquerda
14   
15 def main(page: ft.Page):
16     page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
17     page.vertical_alignment = ft.MainAxisAlignment.CENTER
18
19     def mover(e):
20         e.control.data = (e.control.data % 5) + 1
21         i = e.control.data
22         st.controls.pop()
23         if i==1: ct5=Ct("purple", 0, 60,60,0)
24         elif i==2: ct5=Ct("purple", 0,0,60,60)
25         elif i==3: ct5=Ct("purple", 60,0,0,60)
26         elif i==4: ct5=Ct("purple", 60,60,0,0)
27         else: ct5=Ct("purple", 30,30,30,30)
28         st.controls.append(ct5)
29         st.update()
30
31     ct1 = Ct("red", 0, 60,60,0)
32     ct2 = Ct("yellow", 0,0,60,60)
33     ct3 = Ct("blue", 60,0,0,60)
34     ct4 = Ct("green", 60,60,0,0)
35     ct5 = Ct("purple", 30,30,30,30)
36     ct5.data=0
37     bt_mover = ft.ElevatedButton("Mover", bgcolor="blue", color="white",
38                                   width=120, height= 35, data = 0, on_click=mover)
39
40     st = ft.Stack([ct1, ct2, ct3,ct4, ct5])
41     st.data = 0
42
43     page.add(ft.Container(st, border_radius=8, padding=5,
44                           width=100, height=100, bgcolor="black"), bt_mover)
45
46 ft.app(target=main)
Figura 3: sobreposição de controles com Stack.

O exemplo também ajuda a ilustrar o uso de POO no Flet. Como muitos controles com propriedades semelhantes serão criados, a classe Ct foi criado na linha 3, herdando de um ft.Container. Objetos criados nas linhas 31 a 35 passam para o construtor apenas a cor e a posição do container.

A função mover(), acionada por bt_mover remove o último objeto no Stack na linha 22 e cria um novo container roxo por cima dos demais, circularmente. O container coberto não deixa de existir e reaparece na próxima operação.

Flet: Exemplo 3

Captura de toques de teclado

Atalhos de Teclado

Na seção Widgets: Atalhos de Teclado vimos como capturar a interação do usuário com o aplicativo através de eventos de teclados. A captura de eventos produzidos pelo teclado se dá através do evento page.on_keyboard_event, que gerencia o pressionamento de teclas de letras em combinação com teclas de controle. Esse evento passa o parâmetro e que é uma instância da classe KeyboardEvent, e tem as seguintes propriedades:

e.key Representação textual da tecla pressionada.
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††.

Desta forma conseguimos capturar o pressionamento de uma única letra, além de Enter, Backspace, F1F12, Escape, Insert, Page Down, Pause, etc, ou de combinações como Ctrl-F ou Ctrl-Shift-Enter.

Como exemplo adicional vamos exibir o código de um jogo que captura a interação com o teclado. Uma combinação de teclas como Ctrl-H ou SHIFT-L é exibida em um container que desce do topo da página. Se o usuário digita a mesma combinação ele pontua (10 pontos de cada vez) e nova combinação é exibida.

1   import flet as ft
2   import time, random, string
3
4   cores = ["#FFC6C6", "#A8DCEA", "#BAF3E4", "#F1E9AF",
5            "#CBB1CE", "#B2C9F3", "#F0DCBE", "#F1D7B3"]
6
7   def main(page: ft.Page):
8       def sortear():
9           ct.top = 10        
10          ct.left = random.randrange(100, 1000)
11          ct.height=80
12          t1 = ["Shift", "Alt", "Ctrl"][random.randrange(0, 3)]
13          t2 = random.choice(string.ascii_letters).upper()
14          ct.content = ft.Text(f"{t1}-{t2}", size=20)
15          ct.bgcolor = cores[random.randrange(0, 8)]
16          ct.visible = True
17
18      def fim(e):
19          page.window_destroy()
20
21      def inicio(e):
22          while True:
23              sortear()
24              while ct.top < 400:
25                  time.sleep(.3)
26                  ct.top += 10
27                  page.update()
28              inicio(e)
29
30      def teclou(e):
31          txt = "Shift" if e.shift else "Alt" if e.alt else "Ctrl" if e.ctrl else ""
32          txt = f"{txt}-{e.key}"
33
34          if ct.content.value == txt:
35              pts = int(txtPontos.value.split(":")[1]) + 10
36              txtPontos.value = f"Sua pontuação: {str(pts)}"
37              ct.bgcolor = "red"
38              while ct.top < 400:
39                  time.sleep(.01)
40                  ct.top += 10
41                  ct.height -= 3
42                  page.update()
43
44      ct = ft.Container(padding = 15, width=180, alignment = ft.alignment.center,
45                        border = ft.border.all(2, "black"),
46                        border_radius = ft.border_radius.all(15),
47                        blur=90, visible = False)
48
49      btInicio = ft.ElevatedButton("Começar Jogo", bgcolor="white",
50                                  width=180, height= 40, on_click=inicio)
51      btFim = ft.ElevatedButton("Terminar Jogo", bgcolor="white",
52                                width=180, height= 40, on_click=fim)
53      txtPontos = ft.Text("Sua pontuação: 0", size=27, weight=ft.FontWeight.BOLD)
54      lin = ft.Text("Acerte a combinação de teclas mostrada na tela (Ctrl, Shift, Alt) + Letra",
55                    size=27)
56      linha1 = ft.Row([lin], alignment=ft.MainAxisAlignment.SPACE_EVENLY)
57      linha2 = ft.Row([btInicio, txtPontos, btFim],
58                      alignment=ft.MainAxisAlignment.SPACE_EVENLY)
59
60    page.add(linha1, linha2, ft.Stack([ct]))
61    page.on_keyboard_event = teclou
62
63  ft.app(target=main)

Nesse bloco de código usamos a notação Camel case para dar nomes às variáveis. Ela consiste em usar a primeira letra minúscula e a primeira letra de cada nova palavra subsequente maiúscula. Como exemplo temos casaDaVovo ou notaAluno. O desenvolvedor pode escolher que tipo de notação usar, sendo consistente em seu código e procurando respeitar as convenções da linguagem.

O início do jogo ocorre quando se clica o botão btInicio que dispara a função inicio(). Dentro dela um loop infinito promove várias interações do container descendo a tela (o que é obtido com container.top += 10). Quando o container chega em seu valor máximo estabelecido, no caso ct.top < 400, novos valores são sorteados como suas propriedades e o container e redesenhado no topo.

O sorteio define a posição (top) inicial, uma cor aleatória escolhida dentro de uma lista de cores (linha 15) e monta uma string para representar uma combinação de teclado (linhas 12 a 14). A linha 13 usa random.choice() para escolher aleatoriamente um dos caracteres de string.ascii_letters, e torná-lo maísculo. Esse carater é juntando à um controle. A tecla de controle Meta (Windows) não foi usada pois é comum que ela esteja associada a atalhos globais do computador, em algumas instalações.

A interação do usuário é capturada em teclou que compara a combinação sorteada com aquela teclada pelo usuário. Se ocorreu um acerto ela incrementa a pontuação, derruba o container (acelerando sua queda) e sorteia nova combinação. O loop infinito iniciado na linha 22 só é terminado com o evento btFim.on_click.

Captura de teclas no Python

Claro que podemos capturar o pressionamento de tecla no Python, sem usar os métodos do Flet. Para isso podemos instalar, entre outras escolhas, o módulo keyboard, que funciona em sistemas operacionais Windows e Linux.

# Instale o módulo de teclado usando PIP:
pip install keyboard

# No Python 3 instale usando o comando:
pip3 install keyboard

Para detectar pressionamentos de teclas podemos usar a função is_pressed(). Esse método recebe um caractere como entrada e retorna True se essa tecla foi pressionada. O exemplo seguinte usa um loop que só é terminado com o pressionamento da tecla f.

import keyboard

print("Pressione 'f' para terminar.")
while True:
    if keyboard.is_pressed("a"):
        print("A tecla 'f' foi pressionada!")
        break

A função keyboard.is_pressed("f") retorna False se qualquer outra tecla fopr pressionada.

Também podemos usar a função read_key() para capturar pressionamentos de teclas. Essa função retorna a tecla pressionada pelo usuário.

import keyboard
while True:
    print(keyboard.read_key())
    if keyboard.read_key() == "f":
        print("Você terminou o loop pressionando 'f'.")
        break

Esse código exibe na tela todas as teclas pressionadas até que se tecle “f”.

Outra forma de captura de pressionamento de teclas usa a função wait(), que recebe um caractere como entrada. Quando executado o programa é pausado até que seja pressionada a tecla passada como argumento para a função.

import keyboard
keyboard.wait("f")
print("Você digitou 'f'.")

Nesse último exemplo fica dispensado o uso de um loop para suspender a execução do código.

Bibiografia

Flet: Exemplo 2


Exemplos 2: Referências a controles

Variáveis são referências

Widgets são classes comuns do Python, com suas propriedades e métodos. Para atuar sobre os objetos criados fazemos uma referência a eles, por meio dos nomes de variáveis. Vale lembrar que no Python toda variável é uma refeerência a algum objeto. Por exemplo, no código abaixo, um objeto flet.Text foi atribuído à variável t.

1   import flet as ft
2   
3   def main(page: ft.Page):
4   
5       def mudar_texto(e):
6           t.value="Um texto em azul!"
7           t.color="blue"
8           page.update()
9   
10      t = ft.Text(value="Um texto em vermelho!", color="red", size=20)
11      bt=ft.ElevatedButton("Mudar texto", on_click=mudar_texto)
12      page.add(t,bt)
13
14   ft.app(target=main)
Figura 1

A linha 10 contém o código de inicialização do objeto Text onde atribuimos valor a duas propriedades, respectivamente value (o texto que será exibido) e color (a cor da fonte usada). Com um clique no botão bt as propriedades t.value e t.color são alteradas, usando a variável como referência ao objeto. A figura 1 mostra o estado inical do aplicativo, com o texto em vermelho, e após o clique no botão Mudar texto.

Obs.: para exibir t e bt na mesma linha podemos inserir uma linha na página contendo os dois widgets: page.add(ft.Row([t,bt])). Nesse caso o controle Row (em flet.Row(<lista-de-controles>))) serve de container para os controles na lista <lista-de-controles>.

Relembrando: t é uma referência à uma instância da classe Text.

Vimos que page recebe uma lista (de controles) no parâmetro controls. Essa lista pode ser tratada como qualquer outra lista do Python. Por exemplo, ela possui o método pop(n).

1   for i in range(6):
2       page.controls.append(ft.Text(f"Exibindo a linha {i}"))
3       page.update()
4
5   page.controls.pop()
6   page.update()
Figura 2

Esse código insere e exibe 6 linhas de texto na página. Em seguida ela exclui a última linha com page.controls.pop(). Assim com o fazemos com outras listas, page.controls.pop(n) excluiria a n-ésima linha.

A figura 2 mostra as 5 linhas restantes após a ação de page.controls.pop().

Referências para controles com a Classe Ref

Outro exemplo explora a mesma possibilidade manipulação das variáveis como referências aos objetos de controle. Os objetos TextField são criados com seus textos vazios, preenchidos pelo usuário, usados para inserir a linha 9de cumprimento com o clique do botão. O comando page.update() atualiza na tela apenas as campos que foram alterados. A propriedade autofocus=True na linha 4 garante que o cursor voltará para o objeto nome após a execução da função fala_oi.

1   import flet as ft
2
3   def main(page):
4       nome = ft.TextField(label="Nome", autofocus=True)
5       sobrenome = ft.TextField(label="Sobrenome")
6       coluna_ola = ft.Column()
7   
8       def fala_oi(e):
9           coluna_ola.controls.append(ft.Text(f"Olá, {nome.value} {sobrenome.value}!"))
10          nome.value = ""
11          sobrenome.value = ""
12          page.update()
13          nome.focus()
14    
15      page.add(
16          nome,
17          sobrenome,
18          ft.ElevatedButton("Diga oi!", on_click=fala_oi),
19          coluna_ola,
20      )
21
22  ft.app(target=main)

Em códigos mais longos e complexos um número maior de controles é adicionado, juntamente com suas propriedades e funções que manipulam seus eventos. Fica cada vez mais difícil, para o programador, se lembrar de todas as definições de nomes, por mais organizado que ele seja. A inserção de controles na página, efetuada nas linhas 15 a 20 não deixa muito clara a estrutura de controles inseridos.

Todos os controles do Flet possuem a propriedade ref. De acordo com os propgramadores do Flet esse é um conceito inspirado no React.

Para isso o Flet incluiu uma classe utilitária chamada Ref, usada para fazer uma referência a um controle que pode ser usada em gerenciadores de eventos (event handlers) e, posteriormente, ser conectada a um controle real quando se constroi a árvore do aplicativo.

Para demontrar o uso dessa classe vamos alterar o código do exemplo acima usando Refs. Listamos abaixo como definir uma nova referência, como usar essa referência para inserir valores e, finalmente, como atribuir um controle real a essa referência, aproveitando todas as suas propriedades já definidas.

1   # criar uma referência a um TextField (por exemplo)    
2   nome = ft.Ref[ft.TextField]()
3   
4   # acessar o controle referenciado
5   nome.current.value = "José Ninguém"
6   
7   # atribuindo a referência um controle real, que pode ser incluído na página
8   page.add(
9       ft.TextField(ref=nome, label="Nome", autofocus=True)
10   )

Vemos que objetos da classe Ref possuem a propriedade current que, por sua vez, contém as mesmas propriedades e métodos do pbjeto referenciado. Para ligar essa referência a um controle utilizamos a propriedade Control.ref do controle. Com essas definições a aplicativo pode ser escrito como:

1   import flet as ft
2   
3   def main(page):
4       nome = ft.Ref[ft.TextField]()
5       sobrenome = ft.Ref[ft.TextField]()
6       coluna_ola = ft.Ref[ft.Column]()
7   
8       def fala_oi(e):
9           coluna_ola.current.controls.append(
10              ft.Text(f"Olá, {nome.current.value} {sobrenome.current.value}!")
11          )
12          nome.current.value = ""
13          sobrenome.current.value = ""
14          page.update()
15          nome.current.focus()
16   
17      page.add(
18          ft.TextField(ref=nome, label="Nome", autofocus=True),
19          ft.TextField(ref=sobrenome, label="Sobrenome"),
20          ft.ElevatedButton("Diga oi!", on_click=fala_oi),
21          ft.Column(ref=coluna_ola),
22      )
23
24  ft.app(target=main)
Figura 3

Observe que, fazendo isso, a estrutura da árvore de controles se torna mais claramente visível quando os controles são adicionados à página, na linha 17 e seguintes.

A figura 3 mostra os campos preenchidos e o resultado do clique no botão Diga oi.

Interação com o usuário

Claro que a maioria dos aplicativos demandam algum tipo de interação com o usuário, seja para escolher um ítem de busca, inserir novos dados ou escolher entre opções. Os exemplos acima usam de flet.TextField para a inserção de textos e ft.ElevatedButton para receber cliques e acionar uma função. Claro que existem muitas outras formas de interação que podem ser simples como um clique em botão ou sofisticadas quanto capturar a posição na tela de um clique, dentro de algum objeto desenhado na página.

Caixas de checagens e “dropdowns”

Vimos vários exemplos de uso das caixas de texto puro flet.Text(“Texto a exibir!”), usadas para exibir texto, e caixas interativas flet.TextField onde o usuário pode digitar dados e inserí-los no aplicativo.

As caixas de checagem, flet.Checkbox são úteis quando a escolha de dados é binária, geralmente sim/não.

1   import flet as ft
2   
3   def main(page):
4       def checkbox_mudou(e):
5           texto_exibido.value = f"A caixa de checagem está  {'marcada' if check.value else 'desmarcada'}."
6           page.update()
7
8       texto_exibido = ft.Text()
9       check = ft.Checkbox(label="Clique na caixa de checagem...", value=False, on_change=checkbox_mudou)
10      page.add(check, texto_exibido)
11   
12  ft.app(target=main)
Figura 4

Esse código produz o resultado mostrado na figura, dependendo da caixa estar marcada ou não. O evento capturado nesse caso foi o flet.Checkbox.on_change que envia o evento para a função selecionada. Na função é lida a propriedade booleana check.value. A figura 4 mostra os dois estados possíveis do aplicativo.

Foi usado o operador trinário valor_se_verdadeiro if condição else valor_se_falso.

Dropdowns, flet.Dropdown são úteis quando várias escolhas de dados estão disponíveis. O conjunto permitido de escolhas pode ser inserido durante o desenvolvimento ou alterado pelo usuário.

1   import flet as ft
2
3   def main(page: ft.Page):
4       def dropdown_mudou(e):
5           escolhido.value = f"Você afirmou que prefere {dpd_linguagem.value}"
6           page.update()
7   
8       escolhido = ft.Text()
9       itens_escolher = [
10               ft.dropdown.Option("Python"),
11               ft.dropdown.Option("Java"),
12               ft.dropdown.Option("Javascript"),
13               ft.dropdown.Option("C, C+"),
14               ft.dropdown.Option("Rust"),
15               ft.dropdown.Option("Ruby"),
16               ]
17       dpd_linguagem = ft.Dropdown(
18           label="Linguagem de programação",
19           width=100,
20           options=itens_escolher,
21           on_change=dropdown_mudou,
22       )
23       page.add(dpd_linguagem, escolhido)
24   
25   ft.app(target=main)
Figura 5

Observe que flet.Dropdown.options é uma lista de objetos dropdown.Option(“nome”). O resultado está mostrado na figura 5.

Além do evento change, as caixas dropdown também podem responder a eventos on_blur, disparado quando o controle perde o foco, e on_focus, quando o controle recebe o foco.

Os ítens na caixa de seleção podem ser inseridos ou apagados dinamicamente, em tempo de execução, como mostramos no código seguinte.

1   import flet as ft
2   
3   def main(page: ft.Page):
4       def inserir(e):
5           if txt_insere.value:
6               dp_box.options.append(ft.dropdown.Option(txt_insere.value))
7               dp_box.value, txt_insere.value = txt_insere.value, ""
8               page.update()
9
10      def apagar(e):
11          for item in dp_box.options:
12              if item.key == dp_box.value:
13                  dp_box.options.remove(item)
14          page.update()
15
16      dp_box = ft.Dropdown(width=600)
17      txt_insere = ft.TextField(hint_text="Nome a inserir")
18      bt_insere = ft.ElevatedButton("Inserir", on_click=inserir)
19      bt_apaga = ft.OutlinedButton("Apagar item exibido", on_click=apagar)
20      page.add(dp_box, ft.Row(controls=[txt_insere, bt_insere, bt_apaga]))
21   
22  ft.app(target=main)
Figura 6

Na linha 6 um item é inserido na caixa dropdown. dp_box.options é uma lista que pode ser acrescida de elementos com append. Essa lista é composta de objetos flet.dropdown.Option(texto). A operação de apagar procura por um item nessa lista e o remove, caso encontrado. A propriedade item.key extrai o texto de cada componente da lista. O texte feito na linha 12 é necessário porque tentar remover um item inexistente de uma lista resulta em erro. O aplicativo executado exibe algo como o representado na figura 6.

Capturando cliques e “hovers”

Um exemplo de captura da posição do cursor do mouse no momento do clique pode ser visto na página Layout do Flet: View e Container na seção Container: Eventos onde um clique dentro de um container dispara um evento para exibir as posições do ponto clicado, relativo ao container e à página.

No exemplo abaixo as ações são iniciadas pelo evento flet.Container.on_hover, disparadas quando o cursor do mouse entra ou sai da área delimitada pelo controle. O evento e passado para a função limpar carrega a propriedade e.data == "true" se o cursor entrou na área, e e.data == "false" se saiu dela. Na saída uma cor é escolhida eleatoriamente entre as cores do dicionário cores.

1   import flet as ft
2   import random
3
4   def main(page: ft.Page):
5       cores = {0:"#000000", 1:"#1D74FF", 2:"#C51709", 3:"#FFE000", 4:"#00CB4F",
6                5:"#A866DC", 6:"#FF6600", 7:"#aaffff", 8:"#145375", 9:"#a4b3c5"}
7
8       def limpar(e):
9           page.controls.pop()
10          page.add(matriz())
11          page.update()
12
13      def on_hover(e):
14          if e.data == "true":
15              e.control.bgcolor = "#efefef"
16          else:
17              e.control.bgcolor = cores[random.randrange(10)]
18          e.control.update()
19
20      def matriz():
21          matr = ft.Column()
22          for i in range(10):
23              lin = []
24              for j in range(10):
25                  lin.append(ft.Container(width=50, height=50,
25                             border=ft.border.all(1, "#293B4A"),
27                             border_radius=ft.border_radius.all(10),
28                             bgcolor="#F1EBC5", on_hover=on_hover)
29                  )
30              linha = ft.Row(lin)
31              matr.controls.append(linha)
32          return matr
33
34      tit=ft.Text("Passe o cursor sobre os quadrados", size=18, weight=ft.FontWeight.BOLD)
35      bt_limpar=ft.ElevatedButton("Limpar tudo", icon="arrow_circle_left",
36                bgcolor="white", width=150, height=30, on_click=limpar)
37      page.add(ft.Row([tit,bt_limpar]), matriz())
38
39  ft.app(target=main)

 

Figura 7

O resultado do código está representado na figura 7, após o cursor ter sido passado sobre o objeto matriz(), que é uma coluna.

A construção da matriz de controles container é feita através da função matriz() que retorna 10 linhas, cada uma com 10 containeres, todos respondendo à container.on_hover com a mesma função, que altera a cor de fundo desse objeto.

O laço iniciado na linha 24 constroi um array com 10 objetos Containers (os quadrados). Esse array é inserido em uma linha flet.Row na linha 30. Essas 10 linhas são inseridas na coluna matr na linha 31.

O botão Limpar tudo remove o último controle inserido na página com page.controls.pop(), sendo que esse controle é a matriz de quadrados coloridos. Em seguida ele repõe novos quadrados com as cores originais.

Q&A Religion – 01

About this

These are collected answers I wrote for sites on Questions and Answers, like Quora. I tried to remove duplicates but some may be left still.

Religion

Question: If Jesus’ existence is claimed to be a fact and so are his supposed miracles, why do atheists still choose not to believe in him?

Answer: You don’t need to believe in a thing you know. Beliefs come into play for those things you don’t know, most derived from revelations of a person or a book. I would say it is healthy to keep an open but skeptics mind.


Question: My religion teacher said that there are no atheists because in order to reject God, you must first have a concept of God, and if you have a concept of God, you are not an atheist. In what way is this true, if at all? Why?

Answer: I would agree in some extent. Atheism is a negative position. To that point I would say I am not EVEN an atheist, the same way you are not a-Thor or a-Shiva. Today, to claim you are an atheist is a position against religious ideias that have corrupted the minds for too long.

The ideal position is yet to come. People should not even care about the theistic world view. Absolutely the same way you would not bother to answer me if I claim I have captured a fairy which I keep in a box. You can’t see but you can feel it and be extremely happy if you just believe in it.


Question: If Jesus is the son of God, did God contribute his Y chromosome?

Answer: Wouldn’t it be better to find out if Jesus ever existed, before discussing his Y chromosome?


Question: My eight year old is studying Zen and has an idea related to the “one hand clapping” koan. He says that there really is no “no thing” — even at the edge of space there is the space itself. What do you think?

Answer: In my opinion the Zen strategy to shut up your mind may be beneficial to those who have worked hard their minds before. I’ve met people in zen who just know nothing and think nothing about everything.
Try making him interested in science, reading about biology, evolution, astronomy, and so on.


Question: How do atheists respond to the fine tuning argument?

Answer: It is a question with no clear cut answer, so far. But, different from what Craig Lane and others think, not knowing something is not a good reason to state the existence of a god. (actually it is a very poor argument).
There are some ideas been worked in physics, possible answers. One is the concept of multiverses (instead of one universe). If many universe, with different combination of fundamental constants exists, than we just happen to live in an appropriate universe.

There might also be arguments in the line of evolutionary biology (like, things evolved in the most beneficial way to develop diversity.


Question: If you could delete one and only one thing entirely from this world, what would that be and why?

Answer: Religion, the fear of death and the unknown.


Question: In a universe without God or immortality, how is mankind ultimately different from a swarm of mosquitoes or a barnyard of pigs?

Answer: Well, we share the DNA code, same origin, same life. Bu we have a more complex hardware for thinking and feeling. Most important of all, we humans have the ability to self inquiry, introspection, looking inside and asking why.
This same ability make us fear death, the unknown and because of this we invented a god (or gods).


Question: What is the easiest way to make an atheist believe in god(s)?

Answer: Maybe it is not possible. I would say “show him some evidence”. But, if you have evidence then there is no need for belief.

But there is another answer, more positive: wait until he/she gets really old and scared of death and his/her mental faculties begin to slow down. He/she might believe…


Question: If God exists, why can’t there be multiple gods? Polytheism was once a lot more popular, so if God might exist, why not more than one? And how would they differ from one big Daddy God?

Answer: I think human mind (and brain) is set to find the simplest explanation for all things. There are many colors but the theory shows they are variations of same vibrations of electromagnetic fields. There are many substances but they all are made of the same atoms. Think of the struggle to find an unified field theory for the 4 fields known.
God, and gods are a necessity of human brain (so far) and it would not break the pattern.


Question: In general, why do atheists tend to be hostile to people who believe in God(s), yet demand respect for their beliefs?

Answer: I agree that sometimes non religious people act rude towards religious ones. But I think this is a response because “people of faith” treats badly those who don’t share their beliefs (I mean BAD), specially atheists. Since this topic was never covered before (because there would be no proper place in public to argue against god) this fight may get harsh in near future.

Evangelicals, for instance, can’t see how offensive it is to claim they are the “people of god”, meaning that everyone else will go to hell.


Question: Why do some atheists spell “God” with a lower case, as “god” while writing about the Christian God when it is grammatically correct to capitalize it?

Answer: The bible says no one knows the name of god. So let us clarify: “god” is not a name but a noun. You have god or gods, the same as fairy and spirits. Christians capitalize god in respect to this concept. It IS NOT grammatically correct.


Question: How would you justify/answer the fact that everything came into ‘being’ by itself, without any creator? How did the laws of physics become what they are? Where do the principles of thought come from? Where do feelings come from?

Answer: The answers for these questions (in regard to physics) are not known. Maybe 42! But remember, ignorance is not a good excuse for belief.


Question: Aren’t agnostics the majority?

Answer: Hard to know. Many people, when asked or pooled about their faith, will just go with the larger group in his/her area. This is quite obvious in Brazil where, in doubt, you just say: I’m am a catholic.


Question: Why do atheists try to get agnostics to join their team?

Answer: I see your point. I think of myself as a not-even-atheist. Atheism is a denial of the existence of god or gods. One may as well choose not to discuss this thing. I did not invent the concept (absurd, in my opinion) of god – so I should not be called to decide about it.

It happens, in our times, that there is a fight going on and often you must say which side you favor. In this case I would call myself an atheist. Maybe you are best described as theist (I don’t know). But you DON’T have to take sides, if you don’t want to.


Question: Agnostics: Is it possible to know whether there’s a god?

Answer: I do not know about any god or gods. They may exist or not.
I haven’t seen any good hint they (or she/he) exist. So, why would I devote any of my time to such an improbable concept?


Question: Is the Quran the word of God? Are there any other texts that are the word of God? I heard Dr. Zakir Naik say a text has to pass the test of time in order to be treated as the word of God.

Answer: Can the Quran and the Bible and the Vedas and Bhagavad Gita and The Book of Mormon, and …, and …, be all true simultaneously?


Question: As a non-Muslim, did you read the Quran? What did you think?

Answer: Something doesn’t become true just because a lot of people believe it.
Actually, for most of human history, the majority of things people believes turned to be false. Have you read the bible? The Upanishds? Bhagavad Gita? The Tripitaka?


Question: When will Jesus come back?

Answer: It is said in the Bible that Jesus would be back very soon: “Verily I say unto you, This generation shall not pass, till all these things be fulfilled. ” Matthew:24:34. Isn’t it clear enough he will not come back? Actually if you realize he may not even have ever existed how to expect a “second” coming?


Question: I love both science and God, yet people expect me to take sides. Why can’t I choose both?

Answer: I had a similar dilemma… I don’t think you have to to take sides although I believe they are irreconcilable. The decision is hard to achieve so take as long as you need. Everyone is free to believe in whatever they want. They just should keep in mind that belief is not knowledge.


Question: What argument for the Abrahamic God’s existence do atheists consider the most persuasive?

Answer: None, with all due respect. The only argument I ever knew, as a child, was the fear we might be insulting god. Once you get rid of the fear, sincerely, none of these arguments make any sense. That is not the same as saying I know god doesn’t exist. All I know is that there is no compelling reason to bring such a concept into the debate.
I have friends, thought, who say they have a connection of some sort with something, be it the personal god of the bible or a type of Spinoza god. Who am I to say they are faking it or are deluded? (Even if I think they are!)


Question: Is the Abrahamic God responsible for all of the misery caused by natural disasters?

Answer: No, god is not responsible for that and not for anything else.


Question: If the universe is infinite with infinite planets with infinite possibilities, shouldn’t there be a planet with an actual theological god existing right now?

Answer: Yes, the universe may be (and looks like) infinite. But if god of the Bible exists there he would show up here as well (or he is not infinite and omnipresent). The very concept of god as depicted in the Bible is absurd.


Question: Would atheists agree that everyone believes in God, but it is just the definition of God that we all do not agree on?

Answer: Not at all. I am sure you would not agree with most definitions of “god” so it is not a good practice to change the meaning of the world to accommodate atheists.


Question: God made man in his image. Looking at the Earth today, could God possibly be behind the world’s outlook?

Answer: Sometimes even the question is wrong, making it impossible te answer it properly. Maybe it would be more reasonable to ask: “Supposing there is a god, did he make humans in his image?”

I would not have an answer for that either because it sounds to me very alike: “Aliens planted ebola virus on Earth. Should we be prepared for an invasion?”


Question: Are some theists pretending to believe in God, but deep down they know that God doesn’t exist?

Answer: What would you do if you spent your whole life as a priest (or pastor) depending on the church for your living, being not qualified for any real job, and suddenly finding out you don’t believe in god?


Question: To believe in God or not to believe in God?

Answer: Believe in whatever you want. Just don’t ever forget that believing is not the same as knowing. Believing in god will not cause it to exist, the same as not believing will not cause it to cease existence, in case it does exists.
I don’t believe in god and think there are no serious and compelling reason to care much about the subject. Also I think that people who believe strongly and run their lives (or try to) accordingly to the belief cause harm to themselves.


Question: How does Stephen Hawking prove that there is no god mathematically?

Answer: No one has a mathematical proof that god doesn’t exist. It is not necessary to prove this and it may be impossible to do so. You cannot prove the Invisible Pink Unicorn, or the tea pot around the sun are not real. The point is, can you or anyone else prove there is a god? If not it is just a belief and a tradition. Even if there is a god there is not enough evidence to place it nowhere close to a scientific hypothesis.


Question: What do Christians think happens to non-human animals after death?

Answer: Both the question and the available answers so far make it clear the very idea of a heaven for humans or animals doesn’t make sense. Humans are animals and there are no reason to believe they are so much better they deserve a special treatment when dead.
The evolutionary steps from an furry animal to present day humans are continuous and you can’t say there was a “first man or woman”. When would the soul come into these beings? So, paraphrasing Jack Daniels: ” let us enjoy ourselves while we are here and let us have a good time while alive”!


Question: What are the best quantum theories that support a life-after-death scenario?

Answer: The answer to this question is VERY simple. Quantum theory (not theories) does NOT support life after death. It’s got nothing to do with the subject of spirit, big foots, UFOs, fairies, ghosts … It doesn’t matter if you found a thousand books saying the opposite. We have, so far, no evidence of any link between the quantum theory and an explanation to consciousness (although it may be found, one day…!)
So, why so many authors insist on this sort of connection? First we, human beings, have an urgent need to find a way out of death. We hate the idea that we will be GONE one day. Second, quantum theory is hard to understand … consciousness is hard to understand too … so … voilá they must be related!


Question: Is there an atheist philosopher who is intellectually capable of arguing against William Lane Craig? Craig has done 20+ years of research in the two fields he debates, has published hundreds of academic books and papers on both subjects.

Answer: I guess it is difficult for a religious person to understand you can spend decades over the Bible or other books with religion contents … and it does not mean much. 20+ PHD level on nothing is nothing.
W. Lane talks in soft voice using elaborate words but with little content. Also he picks some points on physics and cosmology but does not show to really understand the epistemology or the inner guts working of science.
To his credit I would agree he is polite and always try to hold the debate on a high level. But just not a match for Richard Dawkings who does not want to debate him because he understands it would be a huge promotion for Lane and pretty much a waste of time for him.


Question: Why is it bad to be materialistic (in a scientific way)?

Answer: I would suggest that the concept of materialism is empty, just as matter itself is made of empty space and fields.


Question: In the materialistic world even spirituality is being treated as a commodity of information, the way it is publicized and marketed that, it is often felt that it can also be purchased at a price. Do you agree?

Answer: I think the word “spiritualism” has no meaning at all, just as we can assign no meaning to the root word “spirit”.
Maybe we can talk about the spirit as being the inner works of humans, their psique, mind, feelings, aspirations, fears … but then I suggest we should not use the word because of its aggregated meaning as “consciousness independent of the body”, something we can not prove to be true.


Question: Can atheists demonstrate without a reasonable doubt that the suffering in our world is meaningless?

Answer: The concept of “meaning for suffering” is purely a human construct, with no correspondence in nature.


Question: Why did eminent scientists like Newton, Einstein, Gauss have a strong belief in the existence of God?

Answer: Many of these scientists studied math and the universe in order to “reveal the glory of god”. That was the mental state in their times and very few people would even dare to think differently. Newton was a great example. He devoted most of his time to study the bible and alchemy. He thought there was a hidden code behind the Bible words to reveal the truth. It happened that, as science progressed no one could find evidence for god. Laplace was asked by Napoleon why he did not mentioned god in his book. He answered: “I had no need of such hypothesis”. Einstein had a very specific notion of god, as some would put, close to the Espinoza view. Not a personal god, not remotely alike the christian god. It is safe to say he would be an atheist if he lived today.


Question: How do atheists explain that 6.5 billion people have evidence for Allah’s existence?

Answer: It is not enough to say they have evidences for Allah’s existence. They have to show that evidence first. Then I would try to explain.


Q&A Science 01

About this

These are collected answers I wrote for sites on Questions and Answers, like Quora. I tried to remove duplicates but some may be left still.

Science

Relativity Theory

Question: How does the Theory of General Relativity work?

Answer: To talk about time we need a way to measure time, the same as a way to measure distances (space). Relativity says all clocks (and rules) will change in moving systems or close to a massive body. It is natural that we expect time and space to be independent on movement because we live in a world of slow speeds (compared to the speed of light). Relativity says that the distance between two points in space (the size of a rule, for instance) is not constant as it is in Newtonian mechanics. To build another constant thing, one that is invariant with motion, you need to include time in your measurement (this is the special theory). Points (x, y, z) are replaced by “events” (x, y, z, t) (where and when) and the interval between two events is now a constant of motion.

To describe gravity Einstein made a generalization of this concept. The “metric” of spacetime (the way to measure distances between two events) changes in the presence of matter (or energy, all the same). The theory says time slows down close to a planet or star (and space shrinks). In this framework time is just another aspect of space. Those statements seem strange but all the predictions of relativity (special and general) have been confirmed by experiments with great precision. So it is a mathematical perfect framework that describes nature in a correct way. This is called a “theory”.

The general theory, together with observations some general assumptions (as homogeneity and isotropy of space, also observed to some degree) leads to a model which includes the Big Bang and a finite age for the universe. The 13 plus something billion years is the time as measured by a “comoving” observer, floating away with the galaxies.
No one expects the theory to hold in any situation. We know already it is not good for very small things that need quantum mechanics. And the theory itself predicts situations in which it fails ( in singularities as black holes or the beginning of the universe).

By the way, there is a good theory that puts quantum mechanics and special theory together, a relativistic quantum theory. It predicts, for instance, the existence of antimatter. There is no good theory yet mixing quantum mechanics and general relativity and this is, I think, the main open problem in theoretical physics.


Question: If somehow I was able to throw a rock at the speed of light towards the sun, would it reach the sun?

Answer: You can’t because no massive body can travel at the speed of light. But, supposing just for fun, you could, the rock would hit the Sun literally “in no time” for there would not be enough time for the heat to warm the rock.
As mentioned in another comment, it is hard to predict what would happen then, because a rock traveling that fast would carry huge amount of energy. Also it would traverse the sun fast … I don’t know what would happen to the sun. (Good example of how accepting unreasonable arguments may lead to weird answers!)


Question: I have heard some people claim Einstein was a fraud. Is there any truth to that claim?

Answer: I think Einstein was brought to public attention for some other reason than purely his science. He was kind a celebrity, friend of Charles Chaplin and many other famous guys. Relativity is pretty much something hard to grasp in terms of everyday experience (so is quantum mechanics). He and his theory became a target for all kinds of nutcrackers. Whoever proves Relativity wrong will be instantly famous.


Question: Is it possible to have a unified theory of everything?

Answer: This is exactly what most theoretical physicists are trying to do. This project has been carried for the last 100 years or so. Needless to say, no success! The main problem is the severe difficulty of putting gravity in the same picture as the other 3 force fields.

We have a pretty sound description of gravity as curvature of space-time (Einstein theory), and for the electromagnetic, weak and strong nuclear in the quantum field theory, mostly done by exchange of virtual particles between interacting objects.
But there is not yet a means of putting the two together.

String theory is one of such attempts. There are many other approaches, one of them considering that gravity is not a real force (not like the others) and formulating quantum field theory in curved space-time – but this is also hard to do.

I would guess there such a theory exists and will be found. I also think math is in the very kernel of everything that exists. But this is a believe, although all we have seen so far supports this idea.


Question: Is there any alternative to the multiverse theory to explain the fine tuning of the cosmological constant?

Answer: An infinite universe with different set of constants in different parts may do the job. Also there may be unknown reasons for some or all of the constants. For example, the square in 1/r^2 for electromagnetic and gravitational forces decay may just be due to geometric reasons (since the area of a sphere around charges grow with r^2.)
We should be clear about things we don’t know and not fear them at all. It will be a sad time when people can not think of open questions.
Even the multiverse hypothesis is very speculative and should not be considered an answer.
For this reason I believe we should call it a hypothesis and never a theory.


Question: Is the gravity theory by Newton true?

Answer: There is no such a thing as “true” in science.
Newton’s theory of gravity, the same as Newtonian mechanics, works really well to describe non relativistic phenomena (weak gravitational fields, low speeds compared to the speed of light).
Otherwise we need to extend the theory (Einstein did it for us, with a little help from his friends, Michelson and Morley, Minkowsky, Riemann, …).
Special and General relativity have worked very well so far to describe all known phenomena. No one knows it will hold true for extreme environment, like very strong gravitational fields and very high energy particles. Probably not!


Question: What is the speed of gravity?

Answer: Photons, and thus light, are excitation of the electromagnetic field. Gravitational waves (and gravitons in case the gravitational field is ever quantized) are excitation of the gravitational field. According to the Relativity theory these waves travel with the speed of light. I am not aware of the status of the experimental (observational) detection of these waves and its speed.


Question: Does light have a gravitational field?

Answer: Light is made of photons which have zero rest mass (or energy, the same). In movement, which it is always, it has mass which, in turn, is the source of gravitational field. The same is true about any other field. If it has energy it has mass.


Question: Why is E=MC^2 so popular?

Answer: First, because it is a simple and compact equation. Easy to remember. Actually it is part of a much more complex equation.

Second, it conveys a deep meaning. Matter and energy are not separate entities but aspects of a higher entity (which we call matter-energy, for lack of a better term). That part is harder to fully understand.

Third, it is very useful and helps us understand many phenomena that occurs daily in ordinary life. They go from nuclear reactions inside stars or nuclear energy plants to chemical effects.


Question: What is the difference between a year and a light year?

Answer: In the language of relativity, special or general, the distance travelled by light in one year and the time taken is one and the same thing.


Question: How do physicists say that Einstein’s theory of relativity breaks down in the interior of a black hole when it is not possible to make observations of the interior of a black hole?

Answer: The equations break down. Some physical properties go to infinite at the singularity. Density, for example. I don’t think there many, if any, physicists who believe the equations are correct at this level. It would probably be necessary a quantum version of relativity at this level.


Question: It is true that science knows nothing about gravity? We still have to realize how it exists and what causes it.

Answer: No, it is not true that “that science does not know nothing of gravity”. Actually we have a pretty good description of gravity both in classical terms and relativity. (The classical case is the limit of the later, when fields are not too strong).

General Relativity is a very clear and precise theory. It describes gravity as a change in geometry of space-time, caused by matter-energy. Unfortunately it is not consistent with the quantum theory of fields that describe the other known 3 fields (weak and strong nuclear and electromagnetic).

We sure have a problem there. There is not yet a quantum theory of gravitation. But that doesn’t mean we know nothing.


Question: Do all modern theories of physics have the same concept of time?

Answer: No. The main accepted theories are built on 3 different concepts of time.

Classical physics and quantum theory (the non relativistic portion, as Schrodinger equation) use the universal time, the same proposed by Newton in his mechanical theory. It is time as an universal flow, independent of space or anything that happens in space.

Electromagnetism and relativistic quantum theory use the same time concept as special relativity, an entity correlated with space. Still a flat (Minkowsky) space-time.

General relativity stands alone with a curved spacetime.


Quantum Theory

Question: Is nature really quantized or is quantization imposed by the mathematical and technological tools used to study natural phenomena?

Answer: Nature is really quantized. All we see in the macro world is an average of many quantum measurements. That means even properties we see with our common perceptions are made of, in principle, of quantum measurements.


Question: Would it be possible to set up a real Schrödinger’s cat experiment?

Answer: Yes, but you would have to kill many cats!


Question: Is quantum physics mostly theory, or has much of it been proven?

Answer: If it is a theory, it has been proven.


Other Topics in Physics

Question: How did the Arabian culture influence Eastern Europe through the ages?

Answer: During the middle ages most classic books (specially Greek works) were destroyed due to christian bigotry. Most books we have today were kept by the Arabs. There were a time when Arabian culture was much more advanced in terms of math and science than European culture. Renaissance was possible because of the Arabs.


Question: Where does the earth get the energy to revolve around the sun?

Answer: By conservation of angular momentum the Earth (and all the other orbiting objects) doesn’t need to receive any energy to keep on rotating. The reason it was first put in motion is a bit more complicated and it has to do with the way the galaxy and later the solar system was formed. The make it short a rotating disk of particles around te Sun gather into blobs (planets) also rotating.


Question: What are some obvious truths that are rarely acknowledged?

Answer: 42.


Question: What beliefs, if any, do we need to do science?

Answer: What about Occam’s razor? Is it a belief? Do we need it?


Question: Why do some of us question authority?

Answer: Some people may know a bit more than you do, in some areas. No one knows everything. No one should be considered an authority except in their areas of expertise (like a doctor in medicine).


Question: How do you explain that it’s the Earth that is rotating on its axis and revolving around the Sun, and not the Sun revolving around the Earth, to someone who is not that educated?

Answer: Just say they are orbiting one another. Since the Sun is much larger and massive, it doesn’t move much from its position.


Question: Where could a person feel the maximum gravity on earth?

Answer: At the sea level. If you can be in a rocket speeding upwards it will be even better.


Question: When a stone is dropped from a high tower, does it land at the foot, to the east (before), or west (behind the Earth’s rotational motion)?

Answer: It lands close to the point below the release point. The rock was rotating with earth before being released. It has angular momentum. But, some fictious forces may deviate the movement, just the kind that moves the Foucault pendulum.


Question: Who are the most famous scientists who believe in god?

Answer: Most scientist in the past were believers. People like Newton did their studies in order to prove “the glory of god”. But they could not do it and eventually people, like Laplace, begun to realize god was not a good hypothesis. So, slowly, most scientist begun either to disbelieve or to try to keep separate religion and science.


Question: Is our mathematics somehow constrained by the laws of physics? If so, could there possibly be alternate universes where the mathematics is completely alien to anything we know?

Answer: I think it is the other way around: Physics, as we understand so far, has to comply with math rules. Math alone is like a game were you can do whatever you want as long as you follow the rules (logic, internal coherence, etc!) Not all of math will be ever be used in physics or in any other application.


Question: Why don’t math professors explain things logically?

Answer: I had good teachers in college, can’t complain.
I think the choice and approach in basic math is very badly done. It makes math too hard and mostly useless (at least to the level most students can grasp). If you disagree ask anyone, who is not working with any aspects of math, what they remember from their courses…

I would point as example the very long calculations with trigonometric functions when all you need is the definition of sine, cossine and tan. In a certain aspect these functions are natural and should be very easy to understand. (I know they don’t look easy…!)

I’ve heard people saying that the modern math reform is to blame for all this. I disagree. What happens is that modern math, still now, have not been fully implemented in teaching curricula. If, when in fundamental level, you can grasp the concept that math IS the study of sets, the relations between elements of the set and between elements of different sets … you are doing good enough.


Question: What is the prime difference between mathematicians and physicists?

Answer: The main difference is that physicists do math with an eye in the “real world”. A theory may be mathematically right but wrong consequences when applied to nature.


Question: Will we ever be able to calculate the size of the universe, and if so, what data do we need before we can do it?

Answer: Hum, we might. And might not! Today we don’t even know if it is finite or not. We can have good estimates of how big is the observable universe and that may be (and is probably) the best we can ever know. Anything that is beyond has no causal relation to us and so, for all practical reasons, is just not inside OUR universe.
Bad thing about all this is that people talk about speculative hypothesis, like multiverses, as if they were proved theories.


Question: What are some software or anything else recommendations, besides Word or OneNote, that I can use to easily take mathematics and physics notes?

Answer: Latex is the (only) answer.
You can use a simple ASCII editor like Notepad to write text, then compile it into beautiful final texts. You would need to learn latex syntax to write things like
E = \frac{mc^2}{\sqrt{1-\frac{v^2}{c^2}}}

In case you do not feel like doing this use a Latex editor.

On the paid side of the software world (belief it or not some people like to pay for software even when you have equal or better quality free and open source similar) you can use Scientific World. It is a WYSIWYG editor (you see, as you type) rendered math on the screen.

There are many free and open source editors. I like Lyx and TexMacs. In any case I suggest you take some time to learn shortcuts for math editing.
Besides being powerful and fun to use either will give you latex sources (which are the only thing used in the scientific community to share docs.)


Question: Can mathematics majors become theoretical physicists?

Answer: Yes, sure. But it is more difficult then doing the inverse, going from physics to math, in my opinion. The reason is the arduous path to learn quantum mechanics. A physics major takes around two years in courses about QM. There is no single discipline in math that takes so long to be grasped.
So, take some time to learn QM. And don’t believe those who say you can pass by only with relativity theory (special and general) which is not a quantum thing and takes much less time and effort to learn.


Question: What on Earth weigh exactly 0.00 pounds?

Answer: Just get any thing at all with adjustable density and make it with the exact density of the air where you make the measurement.


Question: Why is Maxwell considered at Newton’s and Einstein’s level?

Answer: I would remember that Maxwell did (maybe the first) great unification in physics, theoretically speaking. He wrote the full set of equations showing that electricity and magnetism are but different aspects of the same phenomenon.

With this he inaugurated a trend that follows to our days. Now we have a decent unified description of electromagnetic, weak and strong nuclear forces. On the other hand Einstein described gravitational interactions and his theory is in excellent agreement with observational data. BUT there is no theory so far unifying gravity with the other 3 forces.


Question: Can you solve complex math or physics problems only by using intuition?

Answer: Quite often people can tell of a bunch of mathematicians, physicists and others who came out with complex solutions off the box, attributed to intuition alone. But those who have these insights are in fact those who are working hard in a problem, sometimes for years. Intuition is a nice thing and I suppose some have it more then others. But it never came without effort and hard thinking.

A quote attributed to Einstein: “Science is 1% inspiration and 99% perspiration.”
(I could not find out if he really said this!)


Question: How do I prove the flat earth theory?

Answer: We see some questions are wrong by themselves. The Flat Earth “thing” (at best a hypothesis) is not a theory just because it cannot be proven. At the same time it is very easy to disprove the claim, as did Eratosthenes of Cirene in Greece, born about 276 BC. He made a rough estimate of the radius of Earth.

I believe all this talk about flat earth was first proposed, in modern times, as a hoax by someone trying to be funny. But now I see people from everywhere who look serious about that hoax.


Question: How can string theory be called a theory when it’s not experimentally proven? This use diminishes the value of the word theory and enables the phrase it’s just a theory to be used for well-supported theories i.e. creationist’s view on evolution.

Answer: I agree. It should be called The String Hypothesis, or Conjecture.



Question: Who do you think was more impressive, Newton or Einstein?

Answer: I don’t think it is possible to make such a comparison. Newton had his mind filled with superstition. He spent quite a bit of his time studying the Bible and alchemy. It is impossible to say how far he would go if he had spent most of his time with physics and math. On the other hand science as a whole was much simpler at his time.


Question: When reading Maxwell, Faraday, Lord Kelvin and more recently Nikola Tesla and Richard Feynman, all of them compared to others, seem to explain quite complex phenomena with words and without exclusively relying on mathematics. Why?

Answer: There is no proper way to fully describe physical phenomena without math. People can give good descriptions of the theories, better if they understand them well. But there will always be something missing. That means: learn math – at least calculus, of you want to learn physics.


Question: How deep is Deepak Chopra’s understanding of quantum physics?

Answer: When questioned by Richard Dawkins and Leonard Mlodinow, Chopra has agreed to say he talks about quantum stuff as metaphors only. That would be fine if he is clear to everyone about that. The issue is a very serious one since you can make lots of money just working against general understanding of modern physics, which is already very little among the general public.


Question: Why are so many men, usually white males, are jealous of Deepak Chopra and his work on spirituality?

Answer: I don’t know enough about people who disagree with Chopra to conclude they are mostly “white males”. My own problem with him is the very unscientific use of physics (mostly “quantum physics”) to endorse his concepts. There are many people working hard to bring good science education to the general public. We can’t be happy with those who work against it.


Question: Is evolution still a theory?

Answer: Evolution is a fact observed in nature. The explanation that evolution occurs by random mutations and natural selection is a theory. Be sure you understand what is a theory in science.


Question: Which forces does not exist in nature?

Answer: This is not really a well posed question. There is an infinity number of not existent things.

There are only 4 types of forces recognized by science, so far.

  • Electromagnetic
  • Gravitational
  • Strong Nuclear
  • Weak Nuclear

It is a good exercise to explain, in your mind, all kinds of interactions you see in nature in terms of these 4 fields.

It is not impossible that a new force may be found one day in the future. If you find it, you’ll probably get a Nobel Prize.


Question: Why does regular matter carry so little charge?

Answer: It is not true that matter carries little charge. It happens that most blocks of matter carries equal amount of positive (protons) and negative (electrons) charge so they cancel each other. To see electrical effect you have to strip some electrons, which is usually easier them strip protons.


Question: Is negative energy stronger than positive?

Answer: There is nothing as negative energy in physics.


Question: Was Newton jealous of Einstein?

Answer: Only if he could foresee the future!


Flet: Exemplo 1


Flet, exemplos 1

Usando métodos para alterar propriedades de widgets

Os valores de propriedades dos widgets (exceto aqueles que são de leitura somente) podem ser alterados dinamicamente pelo código e por ação do usuário. O código abaixo, além de inserir cidades previamente digitadas em uma lista, permite que usário insira novos nomes.

1   import flet as ft
2   import time
3   
4   def main(page=ft.Page):
5       def inserir(e):
6           txt = txt_cidade.value.strip()
7           if txt:
8               page.controls.append(ft.Text(txt))
9               txt_cidade.value = ""
10              page.update()
11  
12      page.add(ft.Row([ft.Text("Estas são cidades brasileiras")]))
13      txt_cidade = ft.TextField(label="Sua cidade")
14      page.add(
15          ft.Row([
16              txt_cidade,
17              ft.ElevatedButton(text="Insira o nome de sua cidade!", on_click=inserir)
18          ])
19      )
20      cidades = ["Belo Horizonte","Curitiba","São Paulo","Salvador","----------"]
21      for i in range(len(cidades)):
22          page.add(ft.Text(cidades[i]))
23          time.sleep(.5)
24  
25  ft.app(target=main)
Figura 1

Na linha 17 atribuímos uma função ao evento on_click do botão. Essa função é disparada com o clique, enviando o parâmetro e que tem várias propriedades, não utilizadas aqui. A função inserir(e) coleta o conteúdo de txt_cidade, a caixa de texto definida na linha 16, remove espaços em branco nas bordas da string, testa se ela é uma string não vazia e, se não for, cria e insere um texto na página com o conteúdo digitado pelo usuário. Lembrando, na linha 7, if txt só retorna falso se txt for uma string vazia. A execução desse código produz o resultado mostrado na figura 1, após a inserção de nova cidade pelo usuário.

Alterando texto e cores de botões

Outro exemplo abaixo mostra dois botões associados a métodos diferentes, com a capacidade de alterar as propriedades do outro botão.

1   import flet as ft
2   import random
3
4   def main(page: ft.Page):
5       cores = {0:"black", 1:"#1D74FF", 2:"#C51709", 3:"#FFE000", 4:"#00CB4F",
6                5:"#A866DC", 6:"#FF6600", 7:"green", 8:"#145375"}    
7
8       def mudar(e):
9           bt2.disabled = not bt2.disabled
10          bt2.text = "Mudar cor: desabilitado" if bt2.disabled else "Mudar cor: habilitado" 
11          bt1.text="Habilitar" if bt2.disabled else "Desabilitar"
12          page.update()
13
14      def mudar_cor(e):
15          bt1.bgcolor = cores[random.randrange(0,8)]
16          page.update()    
17
18      bt1 = ft.FilledButton(text="Desabilitar", width=250, on_click=mudar)
19      bt2 = ft.ElevatedButton("Mudar cor: habilitado", disabled=False, width=250, on_click=mudar_cor)
20      page.add(ft.Row([bt1, bt2]))
21
22  ft.app(target=main)

Um clique no botão 2 muda a cor do botão 1 escolhendo aleatóriamente entre as cores do dicionário cores. Cliques no botão 1 alternam a habilitação do botão 2.

Figura 2

Fontes, pés de página e referências a widgets

No próximo exemplo definimos duas fontes (de caracteres) para uso no aplicativo, que denominamos respectivamente por Kanit e Karma. A propriedade page.fonts é um dicionário com o nome e local do recurso, a primeira definida como um recurso externo por meio de uma URL, a segunda um recurso interno, na máquina onde roda o aplicativo, explicado abaixo.

A linha 68 define um flet.BottomSheet, uma janela modal (que impede a ação sobre outras partes do aplicativo), que pode ser usada como uma alternativa para uma janela modal ou de menu.

1   import flet as ft
2   
3   def main(page: ft.Page):
4   
5       page.title="Exibindo notas ocultas"
6       page.fonts = {
7           "Kanit": "https://raw.githubusercontent.com/google/fonts/master/ofl/kanit/Kanit-Bold.ttf",
8           "Karma": "fonts/Karma-Regular.ttf",
9       }
10      page.theme = ft.Theme(font_family="Kanit")
11      page.update()
12      
13      def exibe_mensagem(txt):
14          mensagem.value=txt
15          mensagem.update()
16  
17      def traduzir(e):
18          bt2.data = (bt2.data + 1)%2
19          conteudo.current.value = texto_nota[bt2.data]
20          page.update()
21  
22      def bs_fechado(e):
23          exibe_mensagem("A nota foi ocultada por clique fora de sua área.")
24  
25      def mostrar_pe(e):
26          bs.open = True
27          bs.update()
28          exibe_mensagem("A nota está exibida.")
29  
30      def ocultar_pe(e):
31          bs.open = False
32          bs.update()
33          exibe_mensagem("A nota foi ocultada por clique no botão interno.")
34  
35      def fechar_app(e):
36          page.window_destroy()
37  
38      texto_nota=[(
39          'The Selfish Gene is a 1976 book on evolution by ethologist Richard Dawkins, in '
40          'which the author builds upon the principal theory of George C. Williams\'s '
41          'Adaptation and Natural Selection (1966). Dawkins uses the term "selfish gene" as '
42          'a way of expressing the gene-centred view of evolution (as opposed to the views '
43          'focused on the organism and the group), popularising ideas developed during the '
44          '1960s by W. D. Hamilton and others.'
45      ),
46      (
47          'O Gen Egoísta é um livro de 1976 sobre evolução do etólogo Richard Dawkins, no '
48          'qual o autor se baseia na teoria principal de Adaptação e Seleção Natural de '
49          'George C. Williams (1966). Dawkins usa o termo "gene egoísta" como forma de '
50          'expressar a visão da evolução centrada no gene (em oposição às visões focadas no '
51          'organismo e no grupo), popularizando ideias desenvolvidas durante a década de '
52          '1960 por W. D. Hamilton e outros.'
53      )]   
54  
55      bt1=ft.ElevatedButton("Fechar a nota", on_click=ocultar_pe)
56      bt2=ft.ElevatedButton("Traduzir", data=0, on_click=traduzir)
57      bt3=ft.ElevatedButton("Exibir pé de página", on_click=mostrar_pe)
58      bt4=ft.ElevatedButton("Fechar Aplicativo", on_click=fechar_app)
59  
60      mensagem=ft.Text("A nota não está exibida.", font_family="Karma", size=20)
61      conteudo=ft.Ref[ft.Text()]()
62      coluna_texto=ft.Column([ft.Text(ref=conteudo), ft.Row([bt1, bt2])])
63      conteudo.current.font_family="Karma"
64      conteudo.width=600
65      conteudo.current.size=20
66      conteudo.current.value = texto_nota[0]
67  
68      bs = ft.BottomSheet(ft.Container(coluna_texto, padding=50), open=False, on_dismiss=bs_fechado)
69  
70      page.overlay.append(bs)
71      page.add(
72          ft.Text("Clique no botão para exibir a nota oculta", size=30),
73          mensagem,
74          ft.Row([bt3, bt4]),
75      )
76  
77  ft.app(target=main, assets_dir="assets")
Figura 3: posição das fontes

A linha 77, que inicializa o aplicativo do flet, informa que estamos usando o diretório de recursos assets_dir=”assets”, onde podemos armazenar imagens, fontes e outros recursos. No caso do atual aplicativo o diretório code é a pasta raiz, de onde o código será executado. A fonte local Karma-Regular.ttf está gravada em code/assets/fonts/Karma-Regular.ttf, como mostrado na figura 3. Ela é inserida no dicionário page.fonts da linha 6 e utilizada nas linhas 60 e 63. A outra fonte é definida como padrão do aplicativo na linha 10.

A linha 68 inicializa o bs = BottomSheet, inicialmente fechado (invisível). Esse widget é exibido com o clique do botão bt3 (linha 57) e fechado com bt4 (linha 58). O BottomSheet é inserido na página com page.overlay.append(bs) (70). page.overlay é uma lista de controles que são exibidos por cima dos demais controles da página. O botão bt2 (traduzir) altera a exibição do texto em conteudo, escolhendo entre os dois textos armazenados na lista texto_nota. O índice do texto exibido a cada momento está armazenada na propriedade bt2.data.

Outro ponto digno de nota é o uso da referência para um controle usada na linha 61 em conteudo=ft.Ref[ft.Text()](). A classe Ref permite que se defina uma referência para um controle. No cao a referência é feita ao controle de texto associado à variável conteudo. Essa referência permite o uso posterior das propriedades e eventos do controle. Para lidar mais tarde com esse controle usamos a propriedade current como é feito nas linhas 66 e 19.

O resultado desse código ao ser executado é mostrado na figura 4, antes de pressionado o botão Exibir pé de página. A figura 5 exibindo o texto em inglês após pressionamento do botão. Um texto alternativo, em português é exibido quando se clica em Traduzir.

Figura 4: Aplicativo antes de exibir a nota.
Figura 5: Exibindo o texto da nota.

Shebangs e Python no Windows


O que é um Shebang


Vimos que podemos executar comandos do python diretamente no interpretador, obtendo resultados imediatos. Também podemos gravar um arquivo contendo um Shebang #!na primeira linha, informando qual é o interpretador a ser usado nessa execução. Esse conteúdo pode ser lido no artigo Módulos e Pacotes, nesse site. Um exemplo simples pode ser o listado abaixo, gravando o arquivo teste.py.

#!/usr/bin/python3
print("Aprendendo Python no Phylos.net!")

Para executá-lo basta escrever no prompt do terminal, lembrando que, por default arquivos não pode ser executados diretamente por motivos de segurança (pois podem conter instruções maliciosas para o sistema). Eles devem ser tornados executáveis com chmod +x arquivo, o que dá permissão para todos os usuários e todos os grupos.

# a arquivo deve ter permissão do sistema para ser executado como programa
$ chmod +x teste.py
# depois:
$ ./teste.py
# alternativamente podemos executar (sem o #!)
$ python3 /caminho/completo/para/teste.py

# uma única linha no prompt de comando pode ser executada usando a opção -c
$ python3 -c 'print(2*67)'
↳ 134
#
$ /usr/bin/python -c 'print("Usuário")'
↳ Usuário
$ echo $PATH
↳ /var/home/usuario/.local/bin:/var/home/usuario/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin

No caso do comando /usr/bin/python3 o caminho completo para o interpretador (ou um link simbólico para ele) foi fornecido. A linha python3 -c ‘print(2*67)’ também funciona porque python3 está no PATH, o que pode ser verificado com echo $PATH, como mostrado acima.

Se um shebang não for incluído o sistema tentará executar o código na linguagem de comandos da própria shell, por exemplo a BASH shell.

Para que o script somente seja executado se for chamado diretamente do terminal modificamos teste.py usando a variável global __name__. Nada será executado se ele for chamado como módulo. Normalmente não colocamos um shebang em um módulo do Python contendo funções e definições de classes.

#!/usr/bin/python3

if __name__ == "__main__":
    print("Aprendendo Python no Phylos.net!")

O shebang indica, através de um caminho absoluto, onde está o interpretador do Python, lembrando que ele pode variar em cada instalação. Caminhos relativos não são permitidos. Esse escolha aproveita o fato de que o sinal # (cerquilha ou hash, em inglês), representa um comentário no python e em várias outras linguagens de programação.

Essa notação é válida em shells Z shell ou Bash, que são usados em sistema como o macOS e Linux. No Windows ela é ignorada, sem causar danos. Para usar shebangs no Windows você pode instalar o Windows Subsystem for Linux (WSL). Podemos também associar globalmente no Windows arquivos com uma certa extensão (.py nesse caso) e um programa que o executará (como o interpretador Python). Mais sobre Python no Windows abaixo.

Shebang portátil


Como vimos um shebang deve conter o caminho completo (e não relativo) para o interpretador. Dessa forma se o código for executado em outro computador onde o interpretador esteja em local diferente, ele falhará em sua execução.

Para contornar essa questão podemos usar o comando (um aplicativo executável) env (ou printenv) que exibe as variáveis de ambiente (do environment). Se usado sem parâmetros ela simplesmente lista todas as variáveis definidas. Se usada com um parâmetro (no nosso caso o python3 ele indica a posição do interpretador e o acionada, como mostrado no código.

$ env
SHELL=/bin/bash
SESSION_MANAGER=local/unix:@/tmp/.ICE-unix/2035,unix/unix:/tmp/.ICE-unix/2035
COLORTERM=truecolor
...  truncado ...
_=/usr/bin/env

# a última linha mostra onde está esse aplicativo
$ whereis env
env: /usr/bin/env /usr/share/man/man1/env.1.gz

# usado com um parâmetro
$ /usr/bin/env python3
Python 3.12.0 (main, Oct  2 2023, 00:00:00) [GCC 13.2.1 20230918 (Red Hat 13.2.1-3)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>


Nota: Por convencão o arquivo binário env (ou printenv) será sempre encontrado em /usr/bin/. Sua função é localizar arquivos binários executáveis (como python) usando PATH. Independentemented de como o python está instalado seu caminho será adicionado a esta variável e env irá encontrá-lo, caso contrário o python não está instalado. Ele é usado para criar ambientes virtuais, configurando as variáveis de ambiente.

Como resultado desse comportamento podemos escrever um shebang que encontra e executa o interpretador onde ele estiver. Para isso gravamos o arquivo teste.py da seguinte forma:

#!/usr/bin/env python3
print("Uma forma portátil de shebang!")

Como exemplo, podemos executar código em python 2 e python 3 informando qual interpretador queremos usar.

# gravamos 2 arquivos
# python_2.py
#!/usr/bin/env python2
print "Esse rodou no python 2"

# python_3.py
#!/usr/bin/env python3
print("Esse rodou no python 3")

# e os executamos com 
$ ./python_2.py
Esse rodou no python 2

$ ./python_3.py
Esse rodou no python 3

Claro que ambas as versões devem estar instaladas. Observe que, no python 2 o print não é uma função e não exige o uso de parênteses. Podemos verificar qual é a versão do python em uso com o parâmetro -V.

$ /usr/bin/env python -V
Python 3.12.0

Nota: Na minha instalação os comandos python, python3 e python3.12 todos apontam para o mesmo interpretador. No entanto pode ser arriscado usar a forma $ /usr/bin/env python sem definir a versão pois ela pode ter significados diferentes em outras instalações.

Python no Windows

A maioria dos sistemas operacionais como o Unix, Linux, BSD, macOS e outros trazem uma instalação do Python suportada pelo sistema, o que não ocorre com o Windows. Para resolver essa situação a equipe do CPython compilou instaladores para o Windows para que se possa instalar o interpretador e as bibliotecas, para o usuário ou globalmente no sistema. Também são disponibilizados arquivos ZIPs para os módulos adicionais. As versões do Python ficam limitadas a algumas versões do Windows. Por exemplo, o Python 3.12 tem suporte no Windows 8.1 ou mais recentes. Para uso com o Windows 7 é necessário instalar o Python 3.8.

Diversos instaladores estão disponíveis para Windows, cada um com vantagens e desvantagens. O instalador completo contém todos os componentes e é a melhor opção para desenvolvedores que usam Python para projetos variados. O pacote da Microsoft Store é uma instalação simples do Python adequada para executar scripts e pacotes e usar IDLE ou outros ambientes de desenvolvimento. Ele requer Windows 10 ou superior e pode ser instalado com segurança sem corromper outros programas. Ele também fornece muitos comandos convenientes para iniciar o Python e suas ferramentas.

O pacote nuget.org instala um ambiente reduzido, suficientes para pacotes Python e executar scripts, mas não são atualizáveis, além de não possuiren ferramentas de interface de usuário. O pacote embeddable é um pacote mínimo de Python adequado para incorporação em um aplicativo maior sem ser diretamente acessível ao usuário. Uma descrição mais detalhada dos vários pacotes de instalação pode ser encontrada no documento Using Python on Windows.

Os instaladores criam uma entrada do menu Iniciar para o interpretador Python. Também podemos iniciá-lo no prompt de comando, configurando a variável de ambiente PATH. O instalador oferece a opção de configurar isso automaticamente, na opção “Adicionar Python ao PATH”. A localização da pasta Scripts\ também é inserida. Com isso de pode digitar python na linha de comando para executar o interpretador e pip para instalar pacotes. Também é possível executar seus scripts com opções de linha de comando.

A variável PATH também pode ser modificar manualmente para incluir o diretório de instalação do Python, delimitado por ponto e vírgula de outras entradas. Por exemplo ela pode ter a seguinte conteúdo:
C:\WINDOWS\system32;C:\WINDOWS;C:\Program Files\Python 3.9

Inicializador Python para Windows

O lançador, ou inicializador, Python para Windows é um utilitário que permite localizar e executar diferentes versões do Python. Com ele podemos indicar dentro dos scripts , ou na linha de comando, qual a versão do interpretador deve ser usada e executada, como fazemos com o Shebang no Linux ou macOS, independentemente do conteúdo da variável PATH. O inicializador foi originalmente especificado no PEP 397.

É preferível instalar o inicializar por usuário em vez de instalações globais no sistema. Instalações globais no sistema do Python 3.3 e posteriores incluem o inicializador e o adicionam ao PATH. Ele é compatível com todas as versões do Python. Para verificar se o inicializador está disponível, execute o comando py no prompt de comando. Essa e outras formas do comando ficam disponíveis:

$ py
# inicia e mostra a última versão do Python instalada.
# Comandos digitados aqui são enviados diretamente para o Python.

# Se existem mais de um versão instalada, a versão desejada deve ser especificada:
$ py -3.7

# para Python 2, se instalada:
$ py -2

# se o instalador não estiver instalado, a mensagem será mostrada:
$ py
↳ 'py' is not recognized as an internal or external command, operable program or batch file.

# para ver todas as versões do Python instaladas:
$ py --list

Muitas vezes, principalmente quando vamos instalar diversos módulos para desenvolver scripts ou aplicativos, usamos ambiente virtuais, descritos no artigo Ambientes Virtuais, Pip e Conda. Eles podem ser criados com o módulo venv da biblioteca padrão ou virtualenv, uma ferramenta externa. Se o inicializador for executado dentro de um ambiente virtual sem a especificação explícita de versão do Python, ele executará o interpretador do ambiente virtual, ignorando o global. Caso outro interpretador, que não o instalado no ambiente virtual, seja desejado é necessário especificar explicitamente a outra versão do Python.

Por exemplo: Suponha que Pyton3 e Pyton2 estão instalados, e Pyton3 aparece primeiro no PATH. Criamos um arquivo sistema.py com o conteúdo:

#! python
import sys
sys.stdout.write(f"Estamos usando a versão do Python \n (sys.version,)")

# na mesma pasta executamos
$ py sistema.py
# informações sobre Python 3 são exibidas

# Se alteramos o código do script para
#! python2
import sys
sys.stdout.write(f"Estamos usando a versão do Python \n (sys.version,)")

# e executamos
$ py sistema.py
# informações sobre Python 2 são exibidas

# Sub versões podem ser especificadas
! python3.10
# Isso corresponde ao comando
$ py -3.10 sistema.py

Claro que é uma boa prática para desenvolvedores Windows, por compatibilidade, usar o Shebang necessário para execução nos Sistema tipo Unix.

Criando executáveis

O Python não possui suporte integrado para a construção de executáveis independentes. No entanto podemos lançar mão de algumas ferramentas, geralmente desenvolvidos pela comunidade, que resolvem esse problema de alguma forma. As mais populares são as seguintes (os ícones são links para instruções):

Cada um deles possui suas limitações e aspectos fortes de uso. Para definir qual deles usar você deve decidir qual plataforma deseja atingir, pois cada ferramenta de empacotamento suporta um conjunto específico de operações dos sistemas. É melhor que você tome essa decisão logo no início da vida do projeto. Você pode encontrar uma descrição mais precisa e completa dessas ferramentas no texto de Jaworski e Ziadé, citado na bibliografia.

Bibliografia

todos os arquivos acessados em novembro de 2023.

Leia também nesse site:

Flet: Row e Column


Layout do Flet: Row e Column

Flet: Row

Row (linha) é um controle que serve de container para outros controles e os exibe horizontalmente. Ele possui propriedades, eventos e métodos relativos ao layout e gerenciamento de rolagem da página (scroll) para evitar overflow (quando o conteúdo ocupa áerea maior que a disponível na página).

Propriedades de Row

Propriedades Descrição
alignment alinhamento horizontal dos filhos.
A propriedade MainAxisAlignment recebe um ENUM com os valores:

  • START(default) alinha à esquerda da Linha
  • END
  • CENTER
  • SPACE_BETWEEN
  • SPACE_AROUND
  • SPACE_EVENLY

auto_scroll booleano, auto_scroll=True para mover a posição de scroll para o final quando ocorre atualização dos filhos. Para que o método scroll_to() funcione é necessário ajustar auto_scroll=False.
controls uma lista de controles a serem exibidos na linha.
run_spacing espaçamento entre as várias linhas (runs) quando wrap=True. Default: 10.
Linhas adicionais aparecem quando os controles não cabem dentro de uma linha única.
scroll permite rolagem horizontal da linha para evitar overflow. A propriedade pode receber o ENUM ScrollMode com os valores:

  • None (default): não é rolagem e pode haver overflow.
  • AUTO: rolagem habilitada e a barra de rolagem só aparece quando ocorre o scroll.
  • ADAPTIVE: rolagem habilitada e a barra sempre visível quando aplicativo roda na web ou desktop.
  • ALWAYS: rolagem habilitada e a barra sempre visível.
  • HIDDEN: rolagem habilitada e a barra sempre oculta.
spacing espaçamento entre controles na linha. Default: 10 pixeis. O espaçamento só é aplicado quando alignment é start, end ou center.
on_scroll_interval limitação para o evento on_scroll em milisegundos. Default: 10.
tight booleano, espaço a ser ocupado horizontalmente. Default: tight = False, usar todo o espaço os controles.
vertical_alignment alinhamento vertical. A propriedade pode receber o ENUM CrossAxisAlignment os valores:

  • START (default)
  • CENTER
  • END
  • STRETCH
  • BASELINE
wrap booleano, se wrap=True os controles filhos serão colocados em linhas adicionais (chamadas runs), caso não caibam em uma única linha.

Métodos de Row

Método Descrição
scroll_to(offset, delta, key, duration, curve) move a posição de rolagem para o offset absoluto, para um salto (delta) ou para o controle com key especificada.
Detalhes são idênticos ao do método de Column.scroll_to().

Eventos de Row

Evento Dispara quando
on_scroll a posição de rolagem da linha é alterada por um usuário. Consulte Column.on_scroll() para detalhes e exemplos do evento.

Uso das propriedades de row

No código abaixo são criados 30 controles container numerados que são dispostos em uma linha. Dois controle de deslizar (slide) ajustam as propriedades row.width (o número de colunas em cada linha) e row.spacing (o espaçamento entre cada objeto. Quando o número de objetos em uma linha é maior que o espaço permite, novas linhas são inseridas (runs).

import flet as ft # era 52

def main(page: ft.Page):
    def items(count):
        items = []
        for i in range(1, count + 1):
            items.append(ft.Container(ft.Text(value=str(i), color="white", size=20), alignment=ft.alignment.center,
            width=40, height=40, bgcolor="#40A4D2", border_radius=ft.border_radius.all(10)))
        return items

    def muda_largura(e):
        linha.width = float(e.control.value)
        linha.update()

    def muda_separa(e):
        linha.spacing = int(e.control.value)
        linha.update()

    slid_separa = ft.Slider(min=0, max=50, divisions=50, value=0, label="{value}", on_change=muda_separa,)

    slid_largura = ft.Slider(min=0, max=page.window_width, divisions=20, value=page.window_width,
                             label="{value}", on_change=muda_largura,)

    linha = ft.Row(wrap=True, spacing=10, run_spacing=10, controls=items(30), width=page.window_width,)

    txt1 = ft.Text("O primeiro controle seleciona o número de colunas:")
    txt2 = ft.Text("O segundo controle seleciona espaçamento entre colunas:")
    page.add(ft.Column([txt1, slid_largura,]),ft.Column([txt2, slid_separa,]), linha,)

ft.app(target=main)

O código gera, em algum ajuste dos controles de deslizar, a janela abaixo.

Expandindo controles na linha

A expansão de controles na linha e na coluna são análogas. Veja Expandindo controles na linha e na coluna.

Flet: Column

Column é um controle que serve de container para outros controles e os exibe verticalmente. Ele possui propriedades eventos e métodos relativos ao layout e gerenciamento do rolamento da página (scroll) para evitar overflow (quando o conteúdo ocupa áerea maior que a disponível na página.

Propriedades de Column

Propriedades Descrição
alignment define como os controles filhos devem ser colocados verticalmente.
A propriedade MainAxisAlignment recebe um ENUM com os valores:

  • START(default) alinha à esquerda da Linha
  • END
  • CENTER
  • SPACE_BETWEEN
  • SPACE_AROUND
  • SPACE_EVENLY
auto_scroll auto_scroll=True para mover a posição de scroll o final quando ocorre atualização dos filhos. Para que o método scroll_to() funcione devemos fazer auto_scroll=False.
controls lista de controles a serem exibidos na coluna.
horizontal_alignment posicionamento horizontal dos controles filhos.
A propriedade recebe o ENUM CrossAxisAlignment com os valores:

  • START(default) alinha à esquerda da Linha
  • END
  • CENTER
  • STRETCH
  • BASELINE
on_scroll_interval limita o evento on_scroll (em milisegundos). Default: 10.
scroll habilita a rolagem vertical na coluna para evitar overflow de conteúdo.
A propriedade recebe um ENUM opcional ScrollMode com valores:

  • None (default): coluna não é rolável e pode haver overflow.
  • AUTO: rolagem habilitada e a barra de rolagem só aparece quando a rolagem é necessária.
  • ADAPTIVE: rolagem habilitada e a barra sempre visível em aplicativos na web ou desktop.
  • ALWAYS: rolagem habilitada e a barra sempre vivível.
  • HIDDEN: rolagem habilitada, a barra de rolagem está sempre oculta.
spacing espaçamento entre os controles da coluna. Default: 10 pixeis. O espaçamento só é aplicado quando alignment = start, end, center.
run_spacing espaçamento entre “runs” quando wrap=True. Default: 10.
tight espaçamento vertical. Default: False (alocar todo o espaço para filhos).
wrap se wrap=True a coluna distribuirá os controles filho em colunas adicionais (runs) se não couberem em uma coluna.

Métodos de Column

Método Descrição
scroll_to(
offset, delta,
key, duration,
curve)
move a posição de rolagem para o offset absoluto, para um salto (delta) ou para o controle com key especificada.
Por exemplo:

(1) products.scroll_to(offset=100, duration=1000)
(2) products.scroll_to(offset=-1, duration=1000)
(3) products.scroll_to(delta=50)
(4) products.scroll_to(key="20", duration=1000)

(1) offset é a posição do controle, um valor entre a extensão mínima e máxima do controle de scroll.
(2) offset negativo conta a partir do final do scroll. offset=-1 para posicionar no final.
(3) delta move o scroll relativo à posição atual. Rola para trás, se negativo.
(4) key move o scroll para a posição especificada com key.
A maioria dos controles do Flet tem a propriedade key (equivalente ao global key do Flutter. keydeve ser única para toda a page/view.
duration define a duração da animação de rolagem, em milisegundos. Default: 0 (sem animação).
curve configura a curva de animação. Default: ft.AnimationCurve.EASE.

Eventos de Column

Evento Dispara quando
on_scroll a posição de rolagem é alterada por um usuário.
O argumento do gerenciador de eventos é instância da ft.OnScrollEvent com as propriedades:

  • event_type (str), tipo do evento de rolagem:
    • start: início da rolagem;
    • update: controle de rolagem mudou de posição;
    • end: início da rolagem (parou de rolar);
    • user: usuário mudou a direção da rolagem;
    • over: controle ficou inalterado por estar no início ou final;
  • pixels(float): posição de rolagem atual, em pixeis lógicos.
  • min_scroll_extent (float): valor mínimo no intervalo permitido, em pixeis.
  • max_scroll_extent (float): valor máximo no intervalo permitido, em pixeis.
  • viewport_dimension (float): extensão da viewport.
  • scroll_delta (float): distância rolada, em pixeis. Definido apenas em eventos update.
  • direction (str) : direção da rolagem: idle, forward, reverse. Definido apenas em evento user.
  • overscroll (float): número de pixeis não rolados, por overflow. Definido apenas em eventos over.
  • velocity (float): velocidade na posição de ScrollPosition quando ocorreu overscroll. Definido apenas em eventos over.

Expandindo controles na linha e na coluna

Todos os controles possuem a propriedade expand que serve para expandi-lo para preencher os espaços disponíveis dentro de uma linha. Ela pode receber um booleano ou um inteiro. expand=True significa expandir o controle para preencher todo o espaço. expand=int introduz um “fator de expansão” especificando como dividir um espaço com outros controles expandidos na mesma linha, ou coluna. O código:

ft.Row([
    ft.TextField(hint_text="Esse será expandido", expand=True),
    ft.ElevatedButton(text="Esse não...")
])

cria uma linha contendo um TextField que ocupa o espaço disponível, e um ElevatedButton, sem expansão. A expansão é calculada em termos do tamanho de todos os controle na linha. É possível fornecer fatores que definem a proporção de expansão de cada controle. Por exemplo:

linha = ft.Row([
        ft.Container(expand=1, content=ft.Text("A")),
        ft.Container(expand=3, content=ft.Text("B")),
        ft.Container(expand=1, content=ft.Text("C"))
])

cria uma linha com 3 controles ocupando 1, 3, 1 partes em 5, como exibido na figura,

Percentualmente a largura resultante de um filho é calculada como largura = expand / soma( todas as expands) * 100%.

Da mesma forma um controle filho em uma coluna pode ser expandido para preencher o espaço vertical disponível. Por exemplo, o código abaixo cria uma coluna com um Container que ocupando todo o espaço disponível e um controle Text na parte inferior servindo como uma barra de status:

coluna = ft.Column([
         ft.Container(expand=True, content=ft.Text("Esse será expandido")),
         ft.Text("Um texto usado como label")
])

Assim como no controle das linhas, podemos usar fatores numéricos em expand=n.

col = ft.Column([
      ft.Container(expand=1, content=ft.Text("Acima")),
      ft.Container(expand=3, content=ft.Text("No centro")),
      ft.Container(expand=1, content=ft.Text("Abaixo"))
])


Isso cria uma coluna com 3 containeres com alturas de 20% (1/5), 60% (3/5)e 20% (1/5) respectivamente.

Percentualmente a altura resultante de um filho é calculada como altura = expand / soma( todas as expands) * 100%.

Bibiografia

Flet: View e Container


Layout do Flet: View e Container

Flet: View

A palavra container do inglês é traduzida como contêiner (pt-br), plural contêineres. Para não criar confusão com a palavra técnica nós o chamaremos aqui por container, containers.

Um aplicativo do Flet abre sempre uma page que serve de container para o objeto View. Uma View é criado automaticamente quando uma nova sessão é iniciada. Ela é basicamente uma coluna (column) básica, que abriga todos os demais controles que serão inseridos na página. Dessa forma ele tem comportamento semelhante ao de uma column, e as mesmas propriedades. Uma descrição resumida será apresentada aqui. Para maiores detalhes consulte a descrição de column.

O objeto View é o componente visual de uma página Flet, responsável por renderizar os elementos da UI e gerenciar seu estado. Ele pode abrigar outros objetos como botões, campos de texto, imagens, etc, e organizá-los em uma estrutura hierárquica. Esses elementos são então renderizados na tela. O objeto View também possui métodos para lidar com eventos do usuário, como cliques em botões ou textos digitados nas caixas de texto.

Por exemplo, o código:

page.controls.append(ft.Text("Um texto na página!"))
page.update()
# ou, o que é equivalente
page.add(ft.Text("Um texto na página!"))

insere o texto na View que está diretamente criada sobre page. View possui as seguintes propriedades e métodos.

View: Propriedades

Propriedade Descrição
appbar recebe um controle AppBar para exibir na parte superior da página.
auto_scroll Booleano. True para que a barra de rolagem se mova para o final quando os filhos são atualizados. Para que scroll_to() funcione deve ser atribuído auto_scroll=False.
bgcolor Cor de fundo da página.
controls Lista de controles a serem inseridos na página. O último controle da lista pode se removido com page.controls.pop(); page.update().
fullscreen_dialog Booleano. True se a página atual é um diálogo em tela cheia.
route Rota da visualização (não usada atualmente). Pode ser usada para atualizar page.route em caso de nova visualização.
floating_action_button Recebe um controle FloatingActionButton a ser exibido no alto da página.
horizontal_alignment Alinhamento horizontal dos filhos. Default: horizontal_alignment=CrossAxisAlignment.START.
on_scroll_interval Definição do intervalo de tempo para o evento on_scrollo, em milisegundos. Default: 10.
padding Espaço entre o conteúdo do objeto e suas bordas, em pixeis. Default: 10.
scroll Habilita rolagem (scroll) vertical para a página, evitando overflow. O valor da propriedade está em um ENUM ScrollMode com as possibilidades:

  • None (padrão): nenhum scroll. Pode haver overflow.
  • AUTO: scroll habilitado, a barra só aparece quando a rolagem é necessária.
  • ADAPTIVE: scroll habilitado, a barra de rolagem visível quando aplicativo é web ou desktop.
  • ALWAYS: scroll habilitado, a barra sempre exibida.
  • HIDDEN: scroll habilitado, barra de rolagem invisível.
spacing Espaço vertical entre os controles da página, em pixeis. Default: 10. Só aplicado quando alignment = start, end, center.
vertical_alignment Alinhamento vertical dos filhos. A propriedade está em um ENUM MainAxisAlignmente com as possibilidades:

  • START (padrão)
  • END
  • CENTER
  • SPACE_BETWEEN
  • SPACE_AROUND
  • SPACE_EVENLY

Exemplos:

page.vertical_alignment = ft.MainAxisAlignment.CENTER
page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
scroll_to(offset, delta, key, duration, curve) Move a barra de scroll para uma posição absoluta ou salto relativo para chave especificada.

View: Evento

Evento Descrição
on_scroll Dispara quando a posição da barra de rolagem é alterada pelo usuário.

O controle View é útil em situações que se apresenta mais em uma visualização na mesma página e será visto mais tarde com maiores detalhes.

Flet: Container

Um objeto Container é basicamente um auxiliar de layout, um controle onde se pode inserir outros controles, permitindo a decoração de cor de fundo, borda, margem, alinhamento e preenchimento. Ele também pode responder a alguns eventos.

Como exemplo, o código abaixo:

import flet as ft

def main(page: ft.Page):
    page.title = "Contêineres com cores de fundo"

    def cor(e):
        c4 = ft.Container(content=ft.Text("Outro conteiner azul!"), bgcolor=ft.colors.BLUE, padding=5)
        page.add(c4)

    c1 = ft.Container(content=ft.ElevatedButton("Um botão \"Elevated\""),
                      bgcolor=ft.colors.YELLOW, padding=5)

    c2 = ft.Container(content=ft.ElevatedButton("Elevated Button com opacidade=0.5",
                      opacity=0.5), bgcolor=ft.colors.YELLOW, padding=5)

    c3 = ft.Container(content=ft.Text("Coloca outra área azul"),
                      bgcolor=ft.colors.YELLOW, padding=5, on_click=cor)
    page.add(c1, c2, c3)

ft.app(target=main)

gera a janela na figura 1, após 1 clique no botão c3.

Figura 1: Novo container é adicionado ao clicar em “Coloca outra área azul”.

O container c3 reage ao evento clique, adicionando um (ou mais) botão azul à janela.

Container: Propriedades

Figura 2

A figura 2 mostra o esquema de espaçamentos entre controles: a largura e altura (width, height) do container, a margem (margin) entre a caixa de decoração e o container, a borda (border) da caixa e o espaçamento interno (padding) entre o controle e a caixa.

Propriedade Descrição
alignment Alinhamento do controle filho dentro do Container para exibir na parte superior da página. Alignment é uma instância do objeto alignment.Alignment com propriedades x e y que representam a distância do centro de um retângulo.

  • x=0, y=0: o centro do retângulo,
  • x=-1, y=-1: parte superior esquerda do retângulo,
  • x=1.0, y=1.0: parte inferior direita do retângulo.
Figura 3

Constantes de alinhamento pré-definidas no módulo flet.alignment são: top_left, top_center, top_right, center_left, center, center_right, bottom_left, bottom_center, bottom_right. Por exemplo, mostrado na figura 4:

  • container_1.alignment = alignment.center
  • container_2.alignment = alignment.top_left
  • container_3.alignment = alignment.Alignment(-0.5, -0.5)

Figura 4
animate Ativa a animação predefinida do container, alterando valores de suas propriedades de modo gradual. O valor pode ser um dos seguintes tipos:

  • bool: True para ativar a animação do container com curva linear de duração de 1000 milisegundos.
  • int: ajusta tempo em milisegundos, com curva linear.
  • animation: Animation(duration: int, curve: str): ativa animação do container com duração e curva de transição especificadas.

Por exemplo:

import flet as ft

def main(page: ft.Page):

    c = ft.Container(width=200, height=200, bgcolor="red", animate=ft.animation.Animation(1000, "bounceOut"))

    def animar_container(e):
        c.width = 100 if c.width == 200 else 200
        c.height = 100 if c.height == 200 else 200
        c.bgcolor = "blue" if c.bgcolor == "red" else "red"
        c.update()

    page.add(c, ft.ElevatedButton("Animate container", on_click=animar_container))

ft.app(target=main)

O código resulta na animação mostrada abaixo, na figura 5:

Figura 5: animação

bgcolor Cor de fundo do container.
blend_mode modo de mistura (blend) de cores ou gradientes no fundo container.
blur Aplica o efeito de desfoque (blur) gaussiano sobre o container.

O valor desta propriedade pode ser um dos seguintes:

  • um número: especifica o mesmo valor para sigmas horizontais e verticais, por exemplo 10.
  • uma tupla: especifica valores separados para sigmas horizontais e verticais, por exemplo (10, 1).
  • uma instância de ft.Blur: especifica valores para sigmas horizontais e verticais, bem como tile_mode para o filtro. tile_mode é o valor de ft.BlurTileMode tendo como default ft.BlurTileMode.CLAMP.
border Borda desenhada em torno do controle e acima da cor de fundo. Bordas são descritas por uma instância de border.BorderSide, com as propriedades: width (número) e color (string). O valor da propriedade border é instância de border.Borderclasse, descrevendo os 4 lados do retângulo. Métodos auxiliares estão disponíveis para definir estilos de borda:

  • border.all(width, color)
  • border.symmetric(vertical: BorderSide, horizontal: BorderSide)
  • border.only(left: BorderSide, top: BorderSide, right: BorderSide, bottom: BorderSide).

Por exemplo:

container_1.border = ft.border.all(10, ft.colors.PINK_600)
container_1.border = ft.border.only(bottom=ft.border.BorderSide(1, "black"))
border_radius Permite especificar (opcional) o raio de arredondamento das bordas. O raio é instância de border_radius.BorderRadius com as propriedades: top_left, top_right, bottom_left, bottom_right. Esses valores podem ser passados no construtor da instância, ou por meio de métodos auxiliares:

  • border_radius.all(value)
  • border_radius.horizontal(left: float = 0, right: float = 0)
  • border_radius.vertical(top: float = 0, bottom: float = 0)
  • border_radius.only(top_left, top_right, bottom_left, bottom_right)

Por exemplo: container_1.border_radius= ft.border_radius.all(30), fará todas as bordas do container_1 igual 1 30.

clip_behavior Opção para cortar (ou não) o conteúdo do objeto. A propriedade ClipBehavior é um ENUM com valores suportados:

  • NONE
  • ANTI_ALIAS
  • ANTI_ALIAS_WITH_SAVE_LAYER
  • HARD_EDGE

Se border_radius=None o default é ClipBehavior.ANTI_ALIAS. Caso contrário o default é ClipBehavior.HARD_EDGE.

content Define um controle filho desse container.
gradient O gradiente na cor de fundo. O valor deve ser uma instância de uma das classes: LinearGradient, RadialGradient e SweepGradient.


Uma descrição mais detalhada está em Detalhes sobre o gradiente de cores.

image_fit Descrita junto com o objeto image.
image_opacity Define a opacidade da imagem ao mesclar com um plano de fundo: valor entre 0.0 e 1.0.
image_repeat Descrita junto com o objeto image.
image_src Define imagem do plano de fundo.
image_src_base64 Define imagem codificada como string Base-64 como plano de fundo do container.
ink True para efeito de ondulação quando o usuário clica no container. Default: False.
margin Espaço vazio que envolve o controle. margin é uma instância de margin.Margin, definindo a propriedade para os 4 lados do retângulo: left, top, right e bottom. As propriedades podem ser dadas no construtor ou por meio de métodos auxiliares:

  • margin.all(value)
  • margin.symmetric(vertical, horizontal)
  • margin.only(left, top, right, bottom)

Por exemplo:

container_1.margin = margin.all(10)
container_2.margin = 20 # same as margin.all(20)
container_3.margin = margin.symmetric(vertical=10)
container_3.margin = margin.only(left=10)
padding Espaço vazio de decoração entre borda do objeto e seu container. Padding é instância da padding.Padding com propriedades definidas como padding para todos os lados do retângulo: left, top, right e bottom. As propriedades podem ser dadas no construtor ou por meio de métodos auxiliares:

  • padding.all(value: float)
  • padding.symmetric(vertical, horizontal)
  • padding.only(left, top, right, bottom)

Por exemplo:

container_1.padding = ft.padding.all(10)
container_2.padding = 20 # same as ft.padding.all(20)
container_3.padding = ft.padding.symmetric(horizontal=10)
container_4.padding=padding.only(left=10)
shadow Efeito de sombras projetadas pelo container. O valor dessa propriedade é uma instância ou uma lista de ft.BoxShadow, com as seguintes propriedades:

  • spread_radius: espalhamento, quanto a caixa será aumentada antes do desfoque. Default: 0.0.
  • blur_radius: desvio padrão da gaussiano de convolução da forma. Default: 0.0.
  • color: Cor da sombra.
  • offset: Uma instância de ft.Offsetclasse, deslocamentos da sombra, relativos à posição do elemento projetado. Os deslocamentos positivos em x e y deslocam a sombra para a direita e para baixo. Deslocamentos negativos deslocam para a esquerda e para cima. Os deslocamentos são relativos à posição do elemento que o está projetando. Default: ft.Offset(0,0).
  • blur_style: tipo de estilo, ft.BlurStyleque a ser usado na sombra. Default: ft.BlurStyle.NORMAL.

Exemplo:

ft.Container(
    shadow=ft.BoxShadow(
        spread_radius=1,
        blur_radius=15,
        color=ft.colors.BLUE_GREY_300,
        offset=ft.Offset(0, 0),
        blur_style=ft.ShadowBlurStyle.OUTER,
    )
)
shape A forma do conteiner. O valor é ENUM BoxShape: RECTANGLE (padrão), CIRCLE
theme_mode O ajuste do theme_mode redefine o tema usado no container e todos os objetos dentro dele. Se não for definido o tema em theme é válido para o container e seus filhos.
theme Ajuste o tema global e dos filhos na árvore de controle.

Segue um exemplo de uso:

import flet as ft

def main(page: ft.Page):
    page.theme = ft.Theme(color_scheme_seed=ft.colors.RED)

    b1 = ft.ElevatedButton("Botão com tema da página")
    b2 = ft.ElevatedButton("Botão com tema herdado")
    b3= ft.ElevatedButton("Botão com tema dark")

    c1 = ft.Container(
        b1,
        bgcolor=ft.colors.SURFACE_TINT,
        padding=20,
        width=300
    )
    c2 = ft.Container(
        b2,
        theme=ft.Theme(
            color_scheme=ft.ColorScheme(primary=ft.colors.PINK)
        ),
        bgcolor=ft.colors.SURFACE_VARIANT,
        padding=20,
        width=300
    )
    c3 = ft.Container(
        b3,
        theme=ft.Theme(
            color_scheme_seed=ft.colors.INDIGO
        ),
        theme_mode=ft.ThemeMode.DARK,
        bgcolor=ft.colors.SURFACE_VARIANT,
        padding=20,
        width=300
    )

    page.add(c1, c2, c3)

ft.app(main)
Figura 6: Temas

O tema principal da página é definido em page.theme, usando um seed vermelho. Os botões b1 e b2 simnplesmente herdam o tema da página. O botão b3 está no container definido com theme_mode=ft.ThemeMode.DARK, exibindo o tema escuro. O código gera a janela mostrada na figura 6.

Vale lembrar que c1 = ft.Container(b1,...) é equivalente à c1 = ft.Container(content = b1,...) sendo que o content só pode ser omitido se o conteúdo for inserido como primeiro parâmetro.urlDefine a URL a ser abertta quando o container é clicado, disparando o evento on_click.url_target

Define onde abrir URL no modo web:

  • _blank (default): em nova janela ou aba,
  • _self: na mesma janela ou aba aberta.

Container: Eventos

Evento Dispara quando
on_click o usuário clica no container.

class ft.ContainerTapEvent():
    local_x: float
    local_y: float
    global_x: float
    global_y: float

Obs.: O objeto de evento e é uma instância de ContainerTapEvent, exceto se a propriedade ink = True. Nesse caso e será apenas ControlEvent com data vazio.

Um exemplo simples de uso:

import flet as ft

def main(page: ft.Page):

    t = ft.Text()

    def clicou_aqui(e: ft.ContainerTapEvent):
        t.value = (
            f"local_x: {e.local_x}\nlocal_y: {e.local_y}"
            f"\nglobal_x: {e.global_x}\nglobal_y: {e.global_y}"
        )
        t.update()

    c1 = ft.Container(ft.Text("Clique dentro\ndo container"),
                      alignment=ft.alignment.center, bgcolor=ft.colors.TEAL_300, 
                      width=200, height=200, border_radius=10,  on_click=clicou_aqui)
    col = ft.Column([c1, t], horizontal_alignment=ft.CrossAxisAlignment.CENTER)
    page.add(col)

ft.app(target=main)
Figura 8: posição do click.

As propriedades e.local_x e e.local_y se referem à posição dentro do container c1, enquanto e.global_x e e.global_y se referem à posição global, dentro da página.

on_hover o cursor do mouse entra ou abandona a área do container. A propriedade data do evento contém um string (não um booleano) e.data = "true" quando o cursor entra na área, e e.data = "false" quando ele sai.

Um exemplo de um container que altera sua cor de fundo quando o mouse corre sobre ele:

import flet as ft

def main(page: ft.Page):
    def on_hover(e):
        e.control.bgcolor = "blue" if e.data == "true" else "red"
        e.control.update()

    c1 = ft.Container(width=100, height=100, bgcolor="red",
                      ink=False, on_hover=on_hover)
    page.add(c1)

ft.app(target=main)
on_long_press quando o container recebe um click longo (pressionado por um certo tempo).

Detalhes sobre o gradiente de cores

O gradiente na cor de fundo admite como valor uma instância de uma das classes: LinearGradient, RadialGradient e SweepGradient.

Um exmplo de uso está no código abaixo:

import flet as ft
import math

def main(page: ft.Page):
    c1 = ft.Container(
        gradient=ft.LinearGradient(
        begin=ft.alignment.top_center,
        end=ft.alignment.bottom_center,
        colors=[ft.colors.AMBER_900, ft.colors.BLUE],),
        width=150, height=150, border_radius=5,)

    c2 = ft.Container(
         gradient=ft.RadialGradient(colors=[ft.colors.GREY, ft.colors.CYAN_900],),
         width=150, height=150, border_radius=5,)

    c3 = ft.Container(
         gradient=ft.SweepGradient(center=ft.alignment.center,
         start_angle=0.0, end_angle=math.pi * 2,
         colors=[ft.colors.DEEP_PURPLE_800, ft.colors.DEEP_ORANGE_400],),
         width=150, height=150, border_radius=5,)
    
    page.add(ft.Row([c1, c2, c3]))

ft.app(target=main)

O código acima gera as imagens na figura 9:

Figura 9: LinearGradient, a segundo com RadialGradient e a última com SweepGradient

A primeira imagem é gerada com LinearGradient, a segunda com RadialGradient e a última com SweepGradient.

São propriedades da classe LinearGradient:

begin instância de Alignment. Posicionamento inicial (0.0) do gradiente.
end instância de Alignment. Posicionamento final (1.0) do gradiente.
colors cores assumidas pelo gradiente a cada parada. Essa lista deve ter o mesmo tamanho que stops se a lista for não nula. A lista deve ter pelo menos duas cores.
stops lista de valores de 0.0 a 1.0 marcando posições ao longo do gradiente. Se não nula essa lista deve ter o mesmo comprimento que colors. Se o primeiro valor não for 0.0 fica implícita uma parada em 0,0 com cor igual à primeira cor em colors. Se o último valor não for 1.0 fica implícita uma parada em 1.0 e uma cor igual à última cor em colors.
tile_mode como o gradiente deve preencher (tile) a região antes de begin depois de end. O valor é um ENUM GradientTileMode com valores: CLAMP (padrão), DECAL, MIRROR, REPEATED.
rotation rotação do gradiente em radianos, em torno do ponto central de sua caixa container.

Mais Informações:

Gradiente linear na documentação do Flutter.
Unidade de medida de radianos na Wikipedia.

São propriedades da classe RadialGradient:

colors, stops, tile_mode, rotation propriedades idênticas às de LinearGradient.
center instância de Alignment. O centro do gradiente em relação ao objeto que recebe o gradiente. Por exemplo, alinhamento de (0.0, 0.0) coloca o centro do gradiente radial no centro da caixa.
radius raio do gradiente, dado como fração do lado mais curto da caixa. Supondo uma caixa com largura = 100 e altura = 200 pixeis, um raio de 1 no gradiente radial colocará uma parada de 1,0 afastado 100,0 pixeis do centro.
focal ponto focal do gradiente. Se especificado, o gradiente parecerá focado ao longo do vetor do centro até esse ponto focal.
focal_radius raio do ponto focal do gradiente, dado como fração do lado mais curto da caixa. Ex.: um gradiente radial desenhado sobre uma caixa com largura = 100,0 e altura = 200,0 (pixeis), um raio de 1,0 colocará uma parada de 1,0 a 100,0 pixels do ponto focal.

São propriedades da classe SweepGradient:

colors, stops, tile_mode, rotation propriedades idênticas às de LinearGradient.
center centro do gradiente em relação ao objeto que recebe o gradiente. Por exemplo, alinhamento de (0.0, 0.0) coloca o centro do gradiente no centro da caixa.
start_angle ângulo em radianos onde será colocada a parada 0.0 do gradiente. Default: 0.0.
end_angle ângulo em radianos onde será colocada a parada 1.0 do gradiente. Default: math.pi * 2.

Graus e radianos

Figura 10: graus e radianos.

A maiora das medidas angulares na programação do flet (e do python em geral) é dada em radianos. Segue uma breve imagem explicativa do uso de radianos.

Bibiografia


Controles do Flet: Row e Column

Flet: Page, métodos e eventos

Flet, Layout: Page

O objeto page é o primeiro conteiner na construção da árvore de controles do Flet, sendo o único que não está ligado a um conteiner pai. Ele contém o objeto View que, por sua vez abriga todos os outros controles. Uma instância de page e uma view primária são criadas automaticamente quando uma sessão é iniciada.

Métodos de page

Método Ação
can_launch_url(url) Verifica se a url pode ser acessada pelo aplicativo.
Retorna True se é possível gerenciar uma URL com o aplicativo. Caso retorne False isso pode significar que não há como vertificar se o recurso está disponível, talvez devido à falta de permissões. Nas versões mais recentes do Android e iOS esse método sempre retornará False, exceto se o aplicativo for configurado com essa permissão. Na web ele retornará False exceto para esquemas específicos, pois páginas web, por princípio, não devem ter acesso aos aplicativos instalados.
close_banner() Fecha o banner ativo.
close_bottom_sheet() Fecha o pé de página.
close_dialog() Fecha a caixa de diálogo ativa.
close_in_app_web_view() 📱 Fecha visualização de página web iniciada com launch_url() de dentro do aplicativo.
get_clipboard() Recupera o último texto salvo no clipboard do lado do cliente.
go(route) Um método auxiliar para atualizar page.route. Ele aciona o evento page.on_route_change seguido de page.update().
launch_url(url) Abre uma URL em nova janela do navegador.

Abre uma nova página exibindo o recurso descrito na URL.
Admite os argumentos opcionais:

  • web_window_name: nome da janela ou tab de destino. “_self”, na mesma janela/tab, “_blank”, nova janela/tab (ou em aplicativo externo no celular); ou “nome_do_tab”: um nome personalizado.
  • web_popup_window: True para abrir a URL em janela popup. Default: False.
  • window_width – opcional, largura da janela de popup.
  • window_height – opcional, altura da janela de popup.
page.get_upload_url(file_name, expires) Gera URL para armazenamento de upload.
scroll_to(offset, delta, key, duration, curve) Move a posição de scroll para local absoluto ou incremento relativo. Detalhes em scroll_to.
set_clipboard(data) Insere conteúdo no clipboard do lado do cliente (navegador ou desktop). Ex.: page.set_clipboard("Esse valor vai para o clipboard").
show_banner(banner: Banner) Exibe um Banner no pé de página.
show_bottom_sheet(bottom_sheet: BottomSheet) Exibe um BottomSheet no pé de página.
show_dialog(dialog: AlertDialog) Exibe caixa de diálogo.
show_snack_bar(snack_bar: SnackBar) Exibe um SnackBar no pé de página.
window_center() 🖥️ Move a janela do aplicativo para o centro da tela.
window_close() 🖥️ Fecha a janela do aplicativo.
window_destroy() 🖥️ Força o fechamento da janela. Pode ser usado com page.window_prevent_close = True para exigir a confirmação do usuário para encerramento do aplicativo.

import flet as ft

def main(page: ft.Page):
    def fechar(e):
        page.dialog = caixa_dialogo
        caixa_dialogo.open = True
        page.update()

    def sim(e):
        page.window_destroy()

    def nao(e):
        caixa_dialogo.open = False
        page.update()

    caixa_dialogo = ft.AlertDialog(
        modal=True,
        title=ft.Text("Confirme..."),
        content=ft.Text("Você quer realmente fechar o aplicativo?"),
        actions=[
            ft.ElevatedButton("Sim", on_click=sim),
            ft.ElevatedButton("Não", on_click=nao),
        ],
        actions_alignment=ft.MainAxisAlignment.END,
    )

    page.add(ft.Text("Feche a janela do aplicativo clicando o botão \"Fechar\"!"))
    page.add(ft.ElevatedButton("Fechar", icon="close", on_click=fechar, width=250))

ft.app(target=main)

window_to_front() 🖥️ Traz a janela do aplicativo para o primeiro plano.

Eventos de page

Evento Dispara quando
on_close uma sessão expirou por um tempo configurado. Default: 60 minutos.
on_connect o usuário da web conecta ou reconect uma sessão. Não dispara na primeira exibição de uma página mas quando ela é atualizada. Detecta a presença do usuário online.
on_disconnect o usuário se desconecta de uma sessão, fechando o navegador ou a aba da página.on_error ocorre um erro não tratado.
on_keyboard_event
on_resize É o evento disparado quando a janela do aplicativo é redimensionada pelo usuário.

def page_resize(e):
    print(f"A página foi redimensionada para: Laugura = {page.window_width}, Altura = {page.window_height})
page.on_resize = page_resize
on_route_change Evento disparado quando a rota da página é alterada no código, pela alteração da URL no navegador ou uso dos botões de avançar ou retroceder. O objeto e passado automaticamente pelo evento é uma instância da classe RouteChangeEvent:

class RouteChangeEvent(ft.ControlEvent):
    route: str     # passando uma nova rota para a página raiz
on_scroll a posição de scroll é alterada pelo usuário. Tem mesmo comportamento de Column.on_scroll.
on_view_pop Evento disparado quando o usuário clica o botão Back na barra de controle AppBar.
O objeto de evento e é uma instância da classe ViewPopEvent.

class ViewPopEvent(ft.ControlEvent):
    view: ft.View

sendo view uma instância do controle View, o conteiner da AppBar.

on_window_event Evento disparado quando a janela do aplicativo tem uma propriedade alterada: position, size, maximized, minimized, etc.
Pode ser usado com window_prevent_close=True (para interceptar sinal de close) e page.window_destroy() para implementar uma lógica de confirmação de término do aplicativo.

Os nomes eventos de janela possíveis são: close, focus, blur, maximize, unmaximize, minimize, restore, resize, resized (macOS e Windows), move, moved (macOS e Windows), enterFullScreen e leaveFullScreen.

Bibiografia