Flet应用报错AttributeError: 'ControlEvent'无productRow属性排查
问题:Flet POS软件中点击按钮添加容器时触发AttributeError错误
我正在开发一款基于Flet的POS软件,尝试实现点击按钮向ResponsiveRow中添加带指定信息的容器功能,但始终触发错误:AttributeError: 'ControlEvent' object has no attribute 'productRow'。该操作包含在向行发送容器模板的方法中,我参考了一个添加Checkbox的示例实现,但套用后出现问题。
参考示例代码
import flet as ft class TodoApp(ft.UserControl): def build(self): self.new_task = ft.TextField(hint_text="Whats needs to be done?", expand=True) self.tasks = ft.Column() # application's root control (i.e. "view") containing all other controls return ft.Column( width=600, controls=[ ft.Row( controls=[ self.new_task, ft.FloatingActionButton(icon=ft.icons.ADD, on_click=self.add_clicked), ], ), self.tasks, ], ) def add_clicked(self, e): self.tasks.controls.append(ft.Checkbox(label=self.new_task.value)) self.new_task.value = "" self.update() def main(page: ft.Page): page.title = "ToDo App" page.horizontal_alignment = ft.CrossAxisAlignment.CENTER page.update() # create application instance todo = TodoApp() # add application's root control to the page page.add(todo) ft.app(target=main)
我的应用代码(VentaNa.py)
import flet as ft class TopApp(ft.UserControl): def build(self): def close_addProduct(self): addProduct.open = False self.page.update() for i in range(3): NewProduct[i].value = "" def open_addProduct(self): self.page.dialog = addProduct addProduct.open = True self.page.update() def close_Search(self, nameProduct): self.text = nameProduct SearchProducts.close_view(self.text) NewProduct = [ ft.TextField(label="Nombre"), ft.TextField(label="Precio"), ft.TextField(label="Imagen") ] addProduct = ft.AlertDialog( title=ft.Text("Agrega tus productos"), modal=True, content=ft.Column( NewProduct ), actions=[ ft.TextButton(text="Cancelar", on_click=close_addProduct), ft.TextButton(text="Agregar", on_click=CenterApp.submittBttn, ) ], ) AddButton = ft.FloatingActionButton( icon=ft.icons.ADD, on_click=open_addProduct, bgcolor=ft.colors.LIGHT_BLUE_ACCENT_400 ) SearchProducts = ft.SearchBar( view_elevation=4, divider_color=ft.colors.LIGHT_BLUE_ACCENT_400, bar_hint_text="Buscador de productos", view_hint_text="Qué producto estas buscando...", width=900, on_change=None, on_submit=None, controls=[ ft.ListTile(title=ft.Text(), on_click=close_Search) ], ) return ft.Row( controls=[ AddButton, SearchProducts ] ) class CenterApp(ft.UserControl): productRow = ft.ResponsiveRow(controls=[]) def build(self): return ft.Column( width=600, controls=[self.productRow], # Agrega el botón a los controles ) def submittBttn(self, *args): # Los controladores de eventos deben aceptar argumentos self.productRow.controls.append(ft.Container( content=ft.Column( [ ft.Text('hola') ]), margin=10, padding=10, alignment=ft.alignment.center, bgcolor=ft.colors.LIGHT_BLUE_ACCENT_400, width=200, height=200, border_radius=10,)) self.update()
完整报错栈
Exception in thread Thread-79 (submittBttn): Traceback (most recent call last): File "C:\Users\marct\AppData\Local\Programs\Python\Python312\Lib\threading.py", line 1073, in _bootstrap_inner self.run() File "C:\Users\marct\AppData\Local\Programs\Python\Python312\Lib\threading.py", line 1010, in run self._target(*self._args, **self._kwargs) File "C:\Users\marct\OneDrive\Escritorio\CajaDeVenta\SellApp\VentaNa.py", line 75, in submittBttn self.productRow.controls.append(ft.Container( ^^^^^^^^^^^^^^^ AttributeError: 'ControlEvent' object has no attribute 'productRow'
主运行脚本
import flet as ft import VentaNa def main(page: ft.Page): page.title = 'Venta-Na' page.horizontal_alignment = ft.CrossAxisAlignment.CENTER page.window_min_width = 1270 # Minimum window width in pixels page.window_min_height = 800 # Minimum window height in pixels page.update() # Establecer la función de cambio de tamaño como el manejador del evento on_resize sell = VentaNa.TopApp() center = VentaNa.CenterApp() page.add(sell) page.add(center) ft.app(target=main)
问题原因分析
- 事件绑定错误:在
TopApp的弹窗按钮中,直接绑定了CenterApp.submittBttn类方法,而非CenterApp实例的方法。点击按钮时,Flet会将ControlEvent对象作为第一个参数传入,此时方法中的self是ControlEvent实例,而非CenterApp实例,因此找不到productRow属性。 - 类属性误用:
productRow被定义为CenterApp的类属性,所有实例会共享同一行控件,不符合POS软件的独立实例需求。 - 跨实例访问问题:
TopApp无法直接访问CenterApp实例,也无法获取弹窗输入框中的产品信息。 - 嵌套函数作用域混乱:
TopApp中的嵌套函数使用self时,作用域指向不明确,可能引发其他错误。
修复方案及完整代码
修复后的VentaNa.py
import flet as ft class TopApp(ft.UserControl): def __init__(self, center_app): super().__init__() self.center_app = center_app # 保存CenterApp实例引用 self.new_product_fields = [] def build(self): self.new_product_fields = [ ft.TextField(label="Nombre"), ft.TextField(label="Precio"), ft.TextField(label="Imagen") ] self.add_product_dialog = ft.AlertDialog( title=ft.Text("Agrega tus productos"), modal=True, content=ft.Column(self.new_product_fields), actions=[ ft.TextButton(text="Cancelar", on_click=self.close_add_product), ft.TextButton(text="Agregar", on_click=self.submit_product) ], ) add_button = ft.FloatingActionButton( icon=ft.icons.ADD, on_click=self.open_add_product, bgcolor=ft.colors.LIGHT_BLUE_ACCENT_400 ) search_bar = ft.SearchBar( view_elevation=4, divider_color=ft.colors.LIGHT_BLUE_ACCENT_400, bar_hint_text="Buscador de productos", view_hint_text="Qué producto estas buscando...", width=900, on_change=None, on_submit=None, controls=[ ft.ListTile(title=ft.Text(), on_click=self.close_search) ], ) return ft.Row(controls=[add_button, search_bar]) def open_add_product(self, e): self.page.dialog = self.add_product_dialog self.add_product_dialog.open = True self.page.update() def close_add_product(self, e): self.add_product_dialog.open = False # 清空输入框 for field in self.new_product_fields: field.value = "" self.page.update() def submit_product(self, e): # 获取输入值 name = self.new_product_fields[0].value.strip() price = self.new_product_fields[1].value.strip() image_url = self.new_product_fields[2].value.strip() if name and price: # 验证必填字段 self.center_app.add_product_container(name, price, image_url) self.close_add_product(e) def close_search(self, e): search_text = e.control.title.value e.control.parent.close_view(search_text) class CenterApp(ft.UserControl): def build(self): self.product_row = ft.ResponsiveRow(controls=[]) # 改为实例属性 return ft.Column(width=600, controls=[self.product_row]) def add_product_container(self, name, price, image_url): # 创建带产品信息的容器 content = ft.Column([ ft.Text(name, size=16, weight=ft.FontWeight.BOLD), ft.Text(f"Precio: ${price}", size=14), ]) # 如果有图片URL,添加图片控件 if image_url: content.controls.append(ft.Image(src=image_url, width=150, height=100, fit=ft.ImageFit.COVER)) self.product_row.controls.append(ft.Container( content=content, margin=10, padding=10, alignment=ft.alignment.center, bgcolor=ft.colors.LIGHT_BLUE_ACCENT_400, width=200, height=250, border_radius=10, )) self.update()
修复后的主运行脚本
import flet as ft import VentaNa def main(page: ft.Page): page.title = 'Venta-Na' page.horizontal_alignment = ft.CrossAxisAlignment.CENTER page.window_min_width = 1270 page.window_min_height = 800 # 创建CenterApp实例,再传递给TopApp center_app = VentaNa.CenterApp() top_app = VentaNa.TopApp(center_app) page.add(top_app) page.add(center_app) ft.app(target=main)
内容的提问来源于stack exchange,提问作者MarctHidalgo
相关产品推荐
相关产品推荐

