flet-dev / flet

Flet enables developers to easily build realtime web, mobile and desktop apps in Python. No frontend experience required.
https://flet.dev
Apache License 2.0
11.21k stars 433 forks source link

Unable to set Datacell background color #2870

Closed nutanlade closed 7 months ago

nutanlade commented 7 months ago

I want to have a data cell background to be red color. I have multiple ways to set but only background color of text is red rest all is white. I tried different combinations with padding margin but still no luck. Can someone help in solving the issue? Below is the sample code and screenshot of the result. I want whole cell should be in red instead of white.

image

`import flet as ft

def main(page: ft.Page): page.add( ft.DataTable(border=ft.border.all(2, "red"), border_radius=10, horizontal_margin=10, vertical_lines=ft.border.BorderSide(3, "red"), horizontal_lines=ft.border.BorderSide(1, "red"), columns=[ ft.DataColumn(ft.Text("First name")), ft.DataColumn(ft.Text("Last name")), ft.DataColumn(ft.Text("Age"), numeric=True), ], rows=[ ft.DataRow( cells=[ ft.DataCell(ft.Container(ft.Text("Alice"), expand=True, padding=ft.padding.all(0), bgcolor="red")), ft.DataCell(ft.Text("Smith")), ft.DataCell(ft.Text("43")), ], ), ft.DataRow( cells=[ ft.DataCell(ft.Container(ft.Text("Alice"), expand=True, padding=ft.padding.all(0), bgcolor="red")), ft.DataCell(ft.Text("Brown")), ft.DataCell(ft.Text("19")), ], ), ft.DataRow( cells=[ ft.DataCell(ft.Container(ft.Text("Alice"), expand=True, padding=ft.padding.all(0), bgcolor="red")), ft.DataCell(ft.Text("Wong")), ft.DataCell(ft.Text("25")), ], ), ], ), )

ft.app(target=main, view=ft.WEB_BROWSER, port=8502)`

burhansvural commented 7 months ago

@nutanlade

import flet as ft

def main(page: ft.Page):
    page.add(
        ft.DataTable(border=ft.border.all(2, "red"),
        border_radius=10,
        horizontal_margin=10,
        vertical_lines=ft.border.BorderSide(3, "red"),
        horizontal_lines=ft.border.BorderSide(1, "red"),        
        columns=[
            ft.DataColumn(ft.Text("First name")),
            ft.DataColumn(ft.Text("Last name")),
            ft.DataColumn(ft.Text("Age"), numeric=True),
        ],
        rows=[            
            ft.DataRow(                
                cells=[
                    ft.DataCell(
                        ft.Container(
                            content=ft.Text("Alice"),                            
                            padding=ft.padding.all(0),
                            bgcolor="red",
                            width=float("inf")
                        )
                    ),
                    ft.DataCell(ft.Text("Smith")),
                    ft.DataCell(ft.Text("43")),
                ],
            ),
            ft.DataRow(
                cells=[
                    ft.DataCell(ft.Container(ft.Text("Alice"), padding=ft.padding.all(0), bgcolor="red",width=float("inf"))),
                    ft.DataCell(ft.Text("Brown")),
                    ft.DataCell(ft.Text("19")),
                ],
            ),
            ft.DataRow(
                cells=[
                    ft.DataCell(ft.Container(ft.Text("Alice"), padding=ft.padding.all(0), bgcolor="red",width=float("inf"))),
                    ft.DataCell(ft.Text("Wong")),
                    ft.DataCell(ft.Text("25")),
                ],
            ),
        ],
    ),
)

ft.app(target=main)
nutanlade commented 7 months ago

Thanks @burhansvural for your help. I have tried but still some white space is left as below attached image. I need whole cell to be in red color. Made some modifications to your code. Please refer the same below.

image


def main(page: ft.Page):
    page.add(
        ft.DataTable(border=ft.border.all(2, "red"),
        border_radius=10,
        horizontal_margin=20,
        vertical_lines=ft.border.BorderSide(3, "red"),
        horizontal_lines=ft.border.BorderSide(1, "red"),        
        columns=[
            ft.DataColumn(ft.Text("First name")),
            ft.DataColumn(ft.Text("Last name")),
            ft.DataColumn(ft.Text("Age"), numeric=True),
        ],
        rows=[            
            ft.DataRow(                
                cells=[
                    ft.DataCell(
                        ft.Container(
                            content=ft.Text("Alice"),                            
                            padding=ft.padding.all(10),
                            bgcolor="red",
                            width=float("inf")
                        )
                    ),
                    ft.DataCell(ft.Text("Smith")),
                    ft.DataCell(ft.Text("43")),
                ],
            ),
            ft.DataRow(
                cells=[
                    ft.DataCell(ft.Container(ft.Text("Alice"), padding=ft.padding.all(0), bgcolor="red",width=float("inf"))),
                    ft.DataCell(ft.Text("Brown")),
                    ft.DataCell(ft.Text("19")),
                ],
            ),
            ft.DataRow(
                cells=[
                    ft.DataCell(ft.Container(ft.Text("Alice"), padding=ft.padding.all(0), bgcolor="red",width=float("inf"))),
                    ft.DataCell(ft.Text("Wong")),
                    ft.DataCell(ft.Text("25")),
                ],
            ),
        ],
    ),
)

ft.app(target=main)```
burhansvural commented 7 months ago

@nutanlade

import flet as ft

def main(page: ft.Page):
    page.add(
        ft.DataTable(
            border=ft.border.all(2, "red"),

            vertical_lines=ft.border.BorderSide(3, "red"),
            horizontal_lines=ft.border.BorderSide(1, "red"), 
            column_spacing=2,
            horizontal_margin=0,

            columns=[
                ft.DataColumn(ft.Text("First name")),
                ft.DataColumn(ft.Text("Last name")),
                ft.DataColumn(ft.Text("Age"), numeric=True),
            ],
            rows=[            
                ft.DataRow( 

                    selected=True,
                    cells=[
                        ft.Row(                                                        
                            width=float("inf"),
                            expand=True,
                            controls=[
                                ft.Container(
                                    content=ft.Text("Alice",text_align=ft.TextAlign.CENTER,width=float("inf")),
                                    height=float("inf"),
                                    width=float("inf"),
                                    expand=True,
                                    bgcolor=ft.colors.RED,
                                    alignment=ft.alignment.center                                    
                                )                           
                            ]
                        ),
                        ft.DataCell(ft.Text("Smith")),
                        ft.DataCell(ft.Text("43")),
                    ],
                ),            
        ],
    ),
)

ft.app(target=main)

or

import flet as ft

def main(page: ft.Page):
    page.add(
        ft.DataTable(
            border=ft.border.all(2, "red"),

            vertical_lines=ft.border.BorderSide(3, "red"),
            horizontal_lines=ft.border.BorderSide(1, "red"), 
            column_spacing=2,
            horizontal_margin=0,

            columns=[
                ft.DataColumn(ft.Text("First name")),
                ft.DataColumn(ft.Text("Last name")),
                ft.DataColumn(ft.Text("Age"), numeric=True),
            ],
            rows=[            
                ft.DataRow(                     

                    cells=[
                                ft.DataCell(ft.Container(
                                    content=ft.Text("Alice",text_align=ft.TextAlign.CENTER,width=float("inf")),
                                    height=float("inf"),
                                    width=float("inf"),
                                    expand=True,
                                    bgcolor=ft.colors.RED,
                                    alignment=ft.alignment.center 
                                )),
                        ft.DataCell(ft.Text("Smith")),
                        ft.DataCell(ft.Text("43")),
                    ],
                ),            
        ],
    ),
)

ft.app(target=main)

or write a new class extend DataTable

ndonkoHenri commented 7 months ago

There is no proper solution for this, from what I see. I found this SO suggestion which suggests to use linear gradient to paint the column.

Example below:

import flet as ft
def main(page: ft.Page):
    page.add(
        ft.DataTable(border=ft.border.all(2, "red"),
        border_radius=10,
        horizontal_margin=20,
        vertical_lines=ft.border.BorderSide(3, "red"),
        horizontal_lines=ft.border.BorderSide(1, "red"),        
        gradient=ft.LinearGradient(
            begin=ft.alignment.center_left,
            end=ft.alignment.center_right,
            stops=[0.4, 0.4],
            colors=[ft.colors.RED, ft.colors.TRANSPARENT],
        ),
        columns=[
            ft.DataColumn(ft.Text("First name")),
            ft.DataColumn(ft.Text("Last name")),
            ft.DataColumn(ft.Text("Age"), numeric=True),
        ],

        rows=[            
            ft.DataRow(                
                cells=[
                    ft.DataCell(
                        ft.Container(
                            content=ft.Text("Alice"),                            
                            padding=ft.padding.all(10),
                            bgcolor="red",
                            width=float("inf")
                        )
                    ),
                    ft.DataCell(ft.Text("Smith")),
                    ft.DataCell(ft.Text("43")),
                ],
            ),
            ft.DataRow(
                cells=[
                    ft.DataCell(ft.Container(ft.Text("Alice"), padding=ft.padding.all(0), bgcolor="red", expand=True)),
                    ft.DataCell(ft.Text("Brown")),
                    ft.DataCell(ft.Text("19")),
                ],
            ),
            ft.DataRow(
                cells=[
                    ft.DataCell(ft.Container(ft.Text("Alice"), padding=ft.padding.all(0), bgcolor="red",width=float("inf"))),
                    ft.DataCell(ft.Text("Wong")),
                    ft.DataCell(ft.Text("25")),
                ],
            ),
        ],
    ),
)

ft.app(target=main)
burhansvural commented 7 months ago

@nutanlade

This is a solution :

cozum

import flet as ft
dt=ft.DataTable(
            border=ft.border.all(2, ft.colors.RED_200),            
            vertical_lines=ft.border.BorderSide(3, ft.colors.RED_200),
            horizontal_lines=ft.border.BorderSide(1, ft.colors.RED_200), 
            column_spacing=3,
            horizontal_margin=0,

            columns=[
                ft.DataColumn(ft.Text("First name",width=120,text_align=ft.TextAlign.CENTER)),
                ft.DataColumn(ft.Text("Last name",width=120,text_align=ft.TextAlign.CENTER)),
                ft.DataColumn(ft.Text("Age",width=120,text_align=ft.TextAlign.CENTER), numeric=True),
            ],
            rows=[            
                ft.DataRow(                     

                    cells=[
                                ft.DataCell(ft.Container(
                                    content=ft.Text("Alice",text_align=ft.TextAlign.CENTER,width=float("inf")),
                                    height=float("inf"),
                                    width=float("inf"),                                    
                                    bgcolor=ft.colors.RED,
                                    alignment=ft.alignment.center 
                                )),
                                ft.DataCell(ft.Container(
                                    content=ft.Text("Smith",text_align=ft.TextAlign.CENTER,width=float("inf")),
                                    height=float("inf"),
                                    width=float("inf"),                                    
                                    alignment=ft.alignment.center 
                                )),
                                ft.DataCell(ft.Container(
                                    content=ft.Text("43",text_align=ft.TextAlign.CENTER,width=float("inf")),
                                    height=float("inf"),
                                    width=float("inf"),                                    
                                    alignment=ft.alignment.center 
                                )),
                    ],
                ),
                ft.DataRow(                     

                    cells=[
                                ft.DataCell(ft.Container(
                                    content=ft.Text("Alice",text_align=ft.TextAlign.CENTER,width=float("inf")),
                                    height=float("inf"),
                                    width=float("inf"),                                    
                                    bgcolor=ft.colors.RED,
                                    alignment=ft.alignment.center 
                                )),
                                ft.DataCell(ft.Container(
                                    content=ft.Text("Brown",text_align=ft.TextAlign.CENTER,width=float("inf")),
                                    height=float("inf"),
                                    width=float("inf"),                                    
                                    alignment=ft.alignment.center 
                                )),
                                ft.DataCell(ft.Container(
                                    content=ft.Text("19",text_align=ft.TextAlign.CENTER,width=float("inf")),
                                    height=float("inf"),
                                    width=float("inf"),                                    
                                    alignment=ft.alignment.center 
                                )),
                    ],
                ),
                ft.DataRow(                     

                    cells=[
                                ft.DataCell(ft.Container(
                                    content=ft.Text("Alice",text_align=ft.TextAlign.CENTER,width=float("inf")),
                                    height=float("inf"),
                                    width=float("inf"),                                    
                                    bgcolor=ft.colors.RED,
                                    alignment=ft.alignment.center 
                                )),
                                ft.DataCell(ft.Container(
                                    content=ft.Text("Wong",text_align=ft.TextAlign.CENTER,width=float("inf")),
                                    height=float("inf"),
                                    width=float("inf"),                                    
                                    alignment=ft.alignment.center 
                                )),
                                ft.DataCell(ft.Container(
                                    content=ft.Text("25",text_align=ft.TextAlign.CENTER,width=float("inf")),
                                    height=float("inf"),
                                    width=float("inf"),                                    
                                    alignment=ft.alignment.center 
                                )),
                    ],
                ),            
        ],
    )

def main(page: ft.Page):
    page.window_width=500
    page.add(
        ft.SafeArea(
            content=ft.Row(
                alignment=ft.MainAxisAlignment.CENTER,
                vertical_alignment=ft.CrossAxisAlignment.CENTER,
                expand=True,
                controls=[dt]
            )
        )
    )
    page.update()

ft.app(target=main)
nutanlade commented 7 months ago

Thanks @burhansvural and @ndonkoHenri for the help. @burhansvural your last solution worked as expected.

IXIFerzIXI commented 3 months ago

How to change DataCell color on_tap?

import flet as ft
import calendar
import json

# Список сотрудников
employees = ["Сотрудник 1", "Сотрудник 2", "Сотрудник 3", "Сотрудник 4"]

# Статусы
statuses = {
    "P": ("Должен работать", ft.colors.GREEN),
    "O": ("Отпуск или больничный", ft.colors.RED),
    "F": ("Свободен", ft.colors.BLUE),
    "N": ("Нет данных", ft.colors.WHITE)
}

days = {0: "ПН", 1: "ВТ", 2: "СР", 3: "ЧТ", 4: "ПТ", 5: "СБ", 6: "ВС"}

# Состояние выбранных ячеек
selected_cells = []

# Хранение данных таблицы
table_data = {}

def generate_columns():
    columns = [ft.DataColumn(ft.Text("Сотрудник"))]
    for week in calendar.monthcalendar(2024, 7):
        n = 0
        for day in week:
            if day != 0:
                columns.append(ft.DataColumn(ft.Column(controls=[
                    ft.Text(str(day)),
                    ft.Text(days[n])
                ])))
            n += 1
    return columns

def on_tap(e):
    cell = e.control
    print(e.page)
    if cell in selected_cells:
        selected_cells.remove(cell)
        cell.bgcolor = None
    else:
        selected_cells.append(cell)
        cell.bgcolor = ft.colors.YELLOW
    e.page.update()

def generate_rows():
    rows = []
    for employee in employees:
        cells = [ft.DataCell(ft.Text(employee))]
        for _ in range(calendar.monthrange(2024, 7)[1]):
            cell = ft.DataCell(ft.Text("N", bgcolor=ft.colors.RED), on_tap=on_tap)
            cells.append(cell)
        rows.append(ft.DataRow(cells=cells))
    return rows

def main(page: ft.Page):
    page.title = "Table Test"

    def set_status(status):
        status_text, color = statuses[status]
        for cell in selected_cells:
            cell.content.value = status
            cell.bgcolor = color
            cell.update()
        selected_cells.clear()
        save_table_data()
        page.update()

    def save_table_data():
        for row in table.rows:
            employee = row.cells[0].content.value
            table_data[employee] = [cell.content.value for cell in row.cells[1:]]
        with open('table_data.json', 'w', encoding='utf-8') as f:
            json.dump(table_data, f, ensure_ascii=False, indent=4)

    # Создаем кнопки для статусов
    status_buttons = ft.Row(
        controls=[
            ft.ElevatedButton(text=val, on_click=lambda e, s=key: set_status(s)) for key, (val, _) in statuses.items()
        ]
    )

    table = ft.DataTable(
        columns=generate_columns(),
        rows=generate_rows()
    )

    page.add(
        ft.Column(
            controls=[
                status_buttons,
                ft.ListView(
                    controls=[table]
                )
            ]
        )
    )

ft.app(target=main)
burhansvural commented 3 months ago

How to change DataCell color on_tap?

DataCell does not have bgcolor property. Instead, if the control used in the datacell has a bgcolor property, it is assigned to the bgcolor property of that control. Then, it is activated on the screen by typing e.control.update().

1.===========================================

def on_tap(e):
    cell = e.control
    # print(e.page)
    print("сработало событие ontap.")
    # if cell in selected_cells:
    #     selected_cells.remove(cell)
    #     cell.bgcolor = None
    # else:
    #     selected_cells.append(cell)
    #     cell.bgcolor = ft.colors.YELLOW
    e.control.content.bgcolor=ft.colors.YELLOW
    e.control.update()
    # e.page.update()
  1. ===========================================
    def on_tap(e):
    cell = e.control
    # print(e.page)
    print("сработало событие ontap.")
    if cell in selected_cells:
        selected_cells.remove(cell)
        cell.content.bgcolor = ft.colors.TRANSPARENT
        e.control.update()
    else:
        selected_cells.append(cell)
        cell.content.bgcolor = ft.colors.YELLOW
        e.control.update()