这是我的完整代码,除了将表控件添加到页面时之外似乎没有任何其他问题,因为它返回数据来填充所述表,只是当调用填充表的函数时我收到所述错误.
#CONEXION A DB
import flet as ft
from flet import Tab, Tabs
from flet_route import Params, Basket
from Clases.controls import *
#INSTANCIA PARA UTILIZAR LOS CONTROLES
control = Controls()
# Nombre de la tabla
nombre_tabla = "clientes"
# Obtener los nombres de las columnas
nombres_columnas = control.obtenerNombresColumnas(nombre_tabla)
#Style attributes for header class
header_style= {
"height": 60,
"bgcolor": "#081d33",
"border_radius": ft.border_radius.only(top_left=15, top_right=15),
"padding": ft.padding.only(left=15, right=15),
}
#Method that creates and return textfield
def search_field(function: callable):
return ft.TextField(
border_color="transparent",
width=350,
height=20,
text_size=15,
content_padding=0,
cursor_color="white",
cursor_width=1,
color="white",
hint_text="Search",
on_change=function
)
#Method that adds a container to the search field
def search_bar(control: ft.TextField):
return ft.Container(
bgcolor="white10",
border_radius=6,
opacity=0,
animate_opacity=300,
padding=8,
content = ft.Row(
spacing=10,
vertical_alignment="center",
controls=[
ft.Icon(
name=ft.icons.SEARCH_ROUNDED,
size=20,
opacity=0.85
),
control
]
)
)
#Define header class
class Header(ft.Container):
def __init__(self, page):
super().__init__(**header_style,
on_hover=self.toggle_search
)
#Define attributes
#self.dt = dt
self.page = page # Store the 'page' parameter for later use
#Create a textfield for search
self.search_value = search_field(self.filter_data)
#Create a search box
self.search = search_bar(self.search_value)
#Define other class attributes
self.name = ft.Text("DentistaBromista", color="white", size=18, weight=700)
self.logout = ft.IconButton(icon=ft.icons.LOGOUT, icon_color="white", tooltip="Cerrar sesion", on_click=self.logOut, width=40)
#Compile the attributes
self.content = ft.Row(
expand=True,
alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
controls=[
self.name,
self.search,
self.logout
]
)
#Method that log out
def logOut(self, e: ft.TapEvent):
#VALIDAR SI SE HACE CLICK
self.page.go("/") # Use the stored 'page' for redirecting
#Method that toggle search bar visibility
def toggle_search(self, e: ft.HoverEvent):
#SE MUESTRA SI HACES HOVER Y SI NO SE OCULTA
self.search.opacity = 1 if e.data == 'true' else 0
self.search.update()
#Define a placeholder method for filter data
def filter_data(self, e):
print("hola")
#Define form class styling and attributes
form_style = {
"border_radius": 8,
"border": ft.border.all(1, "#ebebeb"),
"bgcolor": "white10",
"padding": 15,
}
#Method that creates and return textfield
def text_field():
return ft.TextField(
border_color="transparent",
height=30,
text_size=15,
content_padding=0,
cursor_color="black",
cursor_width=1,
color="black",
)
#Defin e a container to mantain the textfield
def text_field_container(
expand: bool | int, name: str, control: ft.TextField
):
return ft.Container(
expand=expand,
height=45,
bgcolor="#ebebeb",
border_radius=6,
padding=8,
content=ft.Column(
spacing=1,
controls=[
ft.Text(
value = name,
size=9,
color="black",
weight="bold"
),
control
]
)
)
#Define form class
class formClient(ft.Container):
def __init__(self, page):
super().__init__(**form_style)
#Define attributes
#self.dt = dt
self.page = page # Store the 'page' parameter for later use
#Define the num of rows for textfields
self.row1_value = text_field()
self.row2_value = text_field()
self.row3_value = text_field()
#Define and contain the textfields
self.row1 = text_field_container(True, "Nombre", self.row1_value)
self.row2 = text_field_container(True, "Email", self.row2_value)
self.row3 = text_field_container(True, "Telefono", self.row3_value)
#Button to submit
self.submit = ft.ElevatedButton(
text="Añadir",
style=ft.ButtonStyle(
shape={"": ft.RoundedRectangleBorder(radius=8)},
),
on_click=self.submit_data
)
#Compile the attributes
self.content = ft.Column(
expand=True,
controls=[
ft.Row(controls=[ft.Text("Llena los campos con los datos del cliente", size=20, color="black")]),
ft.Row(controls=[ft.Text("1.Informacion personal ", size=15, color="black")]),
ft.Row(controls=[self.row1, self.row2]),
ft.Row(controls=[self.row3]),
ft.Row(controls=[self.submit], alignment="end")
]
)
#Enviar los datos a la base de datos
def submit_data(self, e:ft.TapEvent=None):
self.row_values = (self.row1_value.value, self.row2_value.value, self.row3_value.value)
print(self.row_values)
# Validar si los campos no están vacíos
if all(self.row_values):
if control.submit_data(e, self.row_values): # Si submit_data devuelve True
self.clear_inputs() # Llamar a clear_inputs
#Mostrar que se insertó
self.page.snack_bar = ft.SnackBar(
content=ft.Text("¡Se guardo correctamente el cliente!", color="white", weight="bold"),
action="Okey!",
bgcolor="green",
action_color="white",
duration=4000)
self.page.snack_bar.open = True
self.page.update()
else:
#Mostrar que no se insertó
self.page.snack_bar = ft.SnackBar(
content=ft.Text("Hubo un problema al guardar el registro.", color="white", weight="bold"),
action="Okey!",
bgcolor="red",
action_color="white",
duration=4000)
self.page.snack_bar.open = True
self.page.update()
else:
dlg = ft.AlertDialog(title=ft.Text("Por favor llena todos los campos", color="white"))
self.page.dialog = dlg
dlg.open = True
self.page.update()
#Method for delete user input after submit
def clear_inputs(self):
#Borra los valores de los campos
self.row1_value.value = ""
self.row2_value.value = ""
self.row3_value.value = ""
self.content.update()
#Datatable styles and attributes
data_table_style = {
"expand": True,
"border_radius": 8,
"border": ft.border.all(2, "#ebebeb"),
"horizontal_lines": ft.border.BorderSide(1, "#ebebeb"),
"columns": [
#Traer los datos de la base de datos(los titulos de las columnas)
ft.DataColumn(ft.Text(index, size=13, color="black", weight="bold"))
for index in [nombres_columnas[i] for i in [1,2,3] ] #MUESTRA SOLO 4 COLUMNAS NOMBRE, TELEFONO, CORREO Y ACCIONES
] + [ft.DataColumn(ft.Text("AGENDAR", size=13, color="black", weight="bold"))] #Columna Acciones
+ [ft.DataColumn(ft.Text("EDITAR", size=13, color="black", weight="bold"))] #Columna Acciones
+ [ft.DataColumn(ft.Text("ELIMINAR", size=13, color="black", weight="bold"))] #Columna Acciones
}
class DataTable(ft.DataTable):
def __init__(self):
super().__init__(**data_table_style)
self.data = control.get_data('clientes')
def add_data_to_table(self):
self.rows = []
for row_dict in self.data: # Itera sobre cada diccionario en la lista
data = ft.DataRow()
data.cells = [
ft.DataCell(
ft.Text(
value, size=13, color="black",
)
) for value in [row_dict['nombre'], row_dict['telefono'], row_dict['email']]
]
data.cells.append(ft.IconButton(ft.icons.EDIT_CALENDAR_ROUNDED))
data.cells.append(ft.IconButton(ft.icons.EDIT))
data.cells.append(ft.IconButton(ft.icons.DELETE))
self.rows.append(data)
self.update()
class mainForm:
def __init__(self):
super().__init__()
self.table = DataTable()
def main(self, page):
page.title = "Registro"
#table = DataTable()
header = Header(page)
form = formClient(page)
content = ft.Column(
expand=True,
controls=[
#Header
header,
ft.Divider(height=2, color="transparent"),
#Form
form,
ft.Divider(height=2, color="transparent"),
#Table
ft.Column(
scroll="auto",
expand=True,
controls=[ft.Row(controls=[self.table])] #tabla
),
],
)
page.add(content)
page.update() # Update the page after adding controls
self.table.add_data_to_table()
return content # Return the content, not the page
#Regresa la vista
def build(self, page: ft.Page, params=Params, basket=Basket):
content = self.main(page)
return ft.View(
"/formCliente",
controls=[content], # Add the content as a control
bgcolor="white"
)
我尝试以不同的方式和在不同的地方添加对函数的调用,以使用从 mysql 带来的数据填充表,但似乎没有任何效果
我不清楚您到底在哪里遇到问题,但可能是从类 init 方法将所有元素添加到页面时出现的问题,您需要在 did_mount() 方法上将其分开,以便在安装控件时添加。
您有一个示例,其中解释了舰队教程的注释: https://flet.dev/docs/tutorials/python-solitaire/