Flet框架page.drawer报错AssertionError:控件需先添加至页面
解决Flet框架中的AssertionError: Control must be added to the page first错误
错误原因分析
- 重复复用同一控件实例:
header控件被同时添加到PaginaInicio和PaginaCuaderno两个自定义控件中,Flet不允许同一个控件实例绑定到多个父容器,路由切换时会触发断言错误。 - Drawer更新逻辑错误:
show_drawer函数中直接调用page.drawer.update(),Drawer作为Page的内置组件,应该通过page.update()来触发页面整体更新。 - 控件实例化错误:
PaginaInicio中直接使用Welcome类而非其实例Welcome(),导致无效控件被添加。
修复方案
- 避免控件实例重复使用:将
header的创建逻辑封装为函数,在每个自定义UserControl的build方法内部调用,确保每个页面都使用独立的header实例。 - 修正Drawer更新方式:将
show_drawer中的page.drawer.update()替换为page.update()。 - 正确实例化控件:将
Welcome改为Welcome()(假设Welcome是Flet控件类)。 - 移除多余的page.add调用:设置
page.drawer后无需手动调用page.add(page.drawer),Flet会自动处理Drawer与页面的关联。
修改后的完整代码
import flet as ft from textos import Welcome def main(page = ft.Page): page.title = 'Mejora tu glucemia' page.padding = ft.padding.only( top = 0, bottom = 0, left = 0, right = 0 ) page.window_height = 900 page.window_width = 400 header_height = page.window_height * 0.08 body_height = page.window_height - header_height def navigation_drawer_changed(e): selected = e.control.selected_index if selected == 0: page.go('/') elif selected == 1: page.go('/cuaderno') page.drawer = ft.NavigationDrawer( on_change= navigation_drawer_changed, controls = [ ft.Container(height=12), ft.NavigationDrawerDestination( label = 'Inicio', icon = ft.icons.DOOR_BACK_DOOR_OUTLINED, selected_icon_content = ft.Icon(ft.icons.DOOR_BACK_DOOR) ), ft.Container(height=12), ft.Container(height=2, bgcolor= ft.colors.BLACK), ft.Container(height=12), ft.NavigationDrawerDestination( label = 'Cuaderno', icon = ft.icons.BOOKMARK_BORDER_OUTLINED, selected_icon_content = ft.Icon(ft.icons.BOOKMARK) ), ft.Container(height=12), ft.NavigationDrawerDestination( label = 'Añadir notas', icon = ft.icons.BORDER_COLOR_OUTLINED, selected_icon_content = ft.Icon(ft.icons.BORDER_COLOR) ) ] ) def show_drawer(e): page.drawer.open = True page.update() # 修正为更新整个页面 # 将header封装为可复用的创建函数 def create_header(): return ft.Container( height= header_height, padding = ft.padding.only( left = page.window_width*0.05, right = page.window_width*0.05 ), shadow = ft.BoxShadow( blur_radius=1, spread_radius=1, color=ft.colors.BLACK, offset=ft.Offset(0, 1), ), bgcolor = ft.colors.BLACK, content = ft.Column( alignment = 'center', controls= [ ft.Row( alignment= 'spaceBetween', controls = [ ft.IconButton(icon = ft.icons.MENU, on_click=show_drawer) ] ) ] ) ) class PaginaInicio(ft.UserControl): def build(self): return ft.Column( spacing= 0, controls= [ create_header(), # 使用独立的header实例 ft.Container( height= body_height, bgcolor= ft.colors.WHITE, content = ft.Row( alignment= 'center', controls = [ ft.Column( alignment= 'center', controls= [ Welcome() # 实例化控件 ] ) ] ) ) ] ) class PaginaCuaderno(ft.UserControl): def build(self): return ft.Column( spacing= 0, controls= [ create_header(), # 使用独立的header实例 ft.Container( height= body_height, bgcolor= ft.colors.WHITE, content = ft.Row( alignment= 'center', controls = [ ft.Column( alignment= 'center', controls= [ ] ) ] ) ) ] ) pagina_inicio = PaginaInicio() pagina_cuaderno = PaginaCuaderno() pages = { '/': ft.View( "/", [ pagina_inicio ] ), '/cuaderno': ft.View( "/cuaderno", [ pagina_cuaderno ] ) } def route_change(route): page.views.clear() page.views.append(pages[page.route]) page.update() page.on_route_change = route_change page.go(page.route) if __name__ == '__main__': ft.app(target=main)
内容的提问来源于stack exchange,提问作者Marcos
相关产品推荐
相关产品推荐

