Flet: MenuBar

Controle MenuBar

Um controle MenuBar é uma barra que normalmente é posta acima da página principal do aplicativo para abrigar um sistema de menus e outros controles usados para as ações principais do usuário. Ela pode conter um sistema de menus composto por submenus e, se desejado, pode ser colocado em qualquer parte do aplicativo.

Propriedades de MenuBar

O controle MenuBar possui poucas propriedades. Como ele pode conter diversos outros controles filhos as formatação e coleta de eventos se dá, em geral, nesses filhos. As seguintes propriedades estão definidas para o controle MenuBar:

Propriedade Descrição
clip_behavior informa de o conteúdo deste controle deve ser cortado (clipped); O valor é do tipo ClipBehavior com default ClipBehavior.NONE.
controls a lista de itens de menu que são os filhos do MenuBar.
style estilização do controle, com valor do tipo MenuStyle.

Exemplo de Uso do MenuBar

import flet as ft

def main(page: ft.Page):
    page.horizontal_alignment = "center"

    def delete(e):
        mensagem.value=""
        page.open(ft.SnackBar(ft.Text("Você apagou as mensagens!")))
        page.update()

    def hover_submenu(e):
        page.open(ft.SnackBar(ft.Text(f"Hover em {e.control.content.value}!")))
        page.update()

    def clique_menu(e):
        mensagem.value+=f"\nClicou em {e.control.content.value}"
        page.update()

    def abre_submenu(e):
        mensagem.value+=f"\nAbrir {e.control.content.value}"
        page.update()

    def fecha_submenu(e):
        mensagem.value+=f"\nFechar {e.control.content.value}"
        page.update()

    icone=[ft.icons.HELP, ft.icons.SAVE, ft.icons.DOOR_BACK_DOOR,
           ft.icons.TEXT_INCREASE , ft.icons.TEXT_DECREASE]

    class MenuItem(ft.MenuItemButton):
        def __init__(self, texto, ico):
            super().__init__()
            self.content=ft.Text(texto)
            self.leading=ft.Icon(icone[ico])
            self.style=ft.ButtonStyle(bgcolor={ft.ControlState.HOVERED: ft.colors.BLUE_100})
            self.on_click=clique_menu

    class SubMenu(ft.SubmenuButton):
        def __init__(self, texto, controles):
            super().__init__()
            self.content=ft.Text(texto)
            self.on_open=abre_submenu
            self.on_close=fecha_submenu
            self.on_hover=hover_submenu
            self.controls=controles

    page.appbar = ft.AppBar(
        title=ft.Text("Demonstração do Controle MenuBar e SnackBar"),
        center_title=True,
        bgcolor=ft.colors.BLUE
    )

    mensagem=ft.Text("", size=20)
    estilo=ft.MenuStyle(alignment=ft.alignment.top_left, bgcolor=ft.colors.RED_300)
    bt_apagar=ft.IconButton(ft.icons.DELETE, icon_color="white", on_click=delete)
    subMenu1=SubMenu("Arquivo",[MenuItem("Sobre", 0), MenuItem("Gravar", 1), MenuItem("Terminar", 2)])
    subMenu2=SubMenu("Visualizar", [SubMenu("Zoom", [MenuItem("Ampliar", 3),MenuItem("Diminuir", 4)])])
    menu_bar=ft.MenuBar(expand=True, style=estilo, controls=[bt_apagar, subMenu1, subMenu2])
    coluna = ft.Column(
        controls=[mensagem],
        height=700,
        alignment=ft.MainAxisAlignment.CENTER
    )

    page.add(ft.Row([menu_bar]), coluna)

ft.app(main)
Figura 1

O resultado desse código está mostrado na figura 1. A primeira imagem mostra o estado ao abrir o aplicativo e passar o cursor do mouse sobre o Menu Arquivo. A segundo mostra o estado após alguns cliques nos submenus de Arquivo. Um clique na lixeira apaga o texto no corpo da página.

Esse exemplo usa o controle SnackBar, que é uma barra de exibição de informações que se abre, temporariamente, no fundo da página do aplicativo.

Duas classes foram definidas:

  • MenuItem, que herda de ft.MenuItemButton e recebe apenas o texto e o ícone a exibir,
  • SubMenu, que herda de ft.SubmenuButton e recebe o texto e o array de controles que serão exibidos.

Esse é um recurso para evitar a declaração repetida de controles que possuem a maioria das propriedades comuns.

Estilo de formatação do código

Nota: adotei nesse bloco de código a prática de declarar os objetos antes de seu uso dentro das propriedades dos controles. Também é possível definir os blocos no ambiente em que são usados. A primeira opção foi usada buscando dar mais clareza ao código. Alguns programadores provavelmente preferem fazer do segundo modo. Esses estilos estão ilustrados abaixo:

# o estilo usado no texto:
    mensagem=ft.Text("", size=20)
    estilo=ft.MenuStyle(alignment=ft.alignment.top_left, bgcolor=ft.colors.RED_300)
    subMenu=SubMenu("Visualizar", [SubMenu("Zoom", [MenuItem("Ampliar"),MenuItem("Diminuir")])])
    menu_bar=ft.MenuBar(expand=True, style=estilo, controls=[subMenu])
    coluna=ft.Column(controls=[mensagem])
    linha=ft.Row([menu_bar])

    page.add(linha, coluna)
    
# alternativamente:

    mensagem=ft.Text("", size=20)
    page.add(
        ft.Row(
            ft.MenuBar(
                expand=True,
                style=ft.MenuStyle(
                    alignment=ft.alignment.top_left,
                    bgcolor=ft.colors.RED_300
                ),
                controls=[
                    SubMenu("Visualizar",
                        [SubMenu("Zoom", [MenuItem("Ampliar"), MenuItem("Diminuir")])]
                    )
                ]
            )
        ),
        ft.Column(controls=[mensagem])
    )


Se essa segunda forma de formatação for adotada é importante manter um sistema coerente de indentação (notando que não se trata da indentação obrigatória do Python para definir blocos).
Observe que a variávelmensagem (um flet.Text) continua sendo definida em separado para poder ser referenciada em uma função fora desse bloco.

Leave a Reply

Your email address will not be published. Required fields are marked *