0

I'm currently facing an issue with the DataTable control within a ListView. The problem is that the scrollbar is not appearing when the data exceeds the window size, causing the content to be cut off.

Here is a simplified version of my code:

import datetime
import random
import flet as ft
from flet_core import Page
from flet_core import UserControl, Row, Column, ListView
from flet_core.dropdown import Option

BORDER = 0.4
LOREM = 'At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat'


def main(page: Page):
    page.title = 'Test App'
    page.add(App(page))


class App(UserControl):
    def __init__(self, page):
        super().__init__()
        self.main_page = page
        today = datetime.date.today()
        self.periods = {
            'Upcoming': (datetime.datetime.today().date() + datetime.timedelta(days=1), (datetime.datetime.today().date() + datetime.timedelta(days=90))),
            'Today': (datetime.datetime.today().date(), today),
            'Yesterday': (today - datetime.timedelta(days=1), today - datetime.timedelta(days=1)),
            'This week': (today - datetime.timedelta(days=today.weekday()), today),
            'Last week': (today - datetime.timedelta(days=today.weekday() + 7),
                          today - datetime.timedelta(days=today.weekday() + 1)),
            'This month': (datetime.date(today.year, today.month, 1), today),
            'Prev. month': (today.replace(month=today.month - 1 if today.month != 1 else 12, day=1), today.replace(day=1) - datetime.timedelta(days=1, seconds=1)),
            'This year': (datetime.date(today.year, 1, 1), datetime.date(datetime.datetime.now().year, 12, 31)),
            'Prev. year': (datetime.date(today.year - 1, 1, 1), datetime.date(today.year, 1, 1)),
            'All time': (datetime.date(2016, 1, 1), datetime.date(2050, 1, 1))
        }

    def build(self):
        self.search_field = ft.TextField(label='Search...',
                                         border_width=BORDER)
        self.only_my_tls = ft.Checkbox(label='only my',
                                       value=False)
        self.delivered = ft.Checkbox(label='delivered',
                                     value=True)
        self.paid = ft.Checkbox(label='paid',
                                value=True)
        self.period_cb = ft.Dropdown(options=[
            Option(x) for x in self.periods.keys()
        ],
            border_width=BORDER,
            label='Period...'
        )

        return Column(
                controls=[
                    Row(
                        [
                            self.search_field,
                            Row(expand=True),
                            self.only_my_tls,
                            self.delivered,
                            self.paid,
                            self.period_cb
                        ],
                        spacing=40),
                    Column([
                        Row(
                            controls=[
                                ListView(
                                    controls=[
                                        self.table()
                                    ],
                                    expand=True,
                                )
                            ],
                        )
                    ])
                ],
                scroll=ft.ScrollMode.AUTO,
            )

    def table(self):
        def generate_columns():
            columns = []
            for c in range(7):
                columns.append(ft.DataColumn(ft.Text(f'Column {c}')))
            self.main_page.columns = columns
            return columns

        def generate_rows():
            rows = []
            for row in range(1, 100):
                cells = []
                for _ in range(len(self.main_page.columns)):
                    words = LOREM.split()
                    sentence_length = random.randint(1, 7)
                    selected_words = random.sample(words, sentence_length)
                    sentence = ' '.join(selected_words)
                    cells.append(ft.DataCell(ft.Text(sentence)))
                rows.append(ft.DataRow(cells=cells))
            return rows

        table = ft.DataTable(expand=True,
                             columns=generate_columns(),
                             rows=generate_rows(),
                             border=ft.border.all(BORDER, "grey"),
                             border_radius=10,
                             vertical_lines=ft.BorderSide(width=BORDER, color='grey'),
                             heading_row_color=ft.colors.with_opacity(0.1, ft.colors.GREEN_400),
                             )
        return table


ft.app(target=main)

I tried to set 'scroll=True' property to parent Column, it has no effect. The scrollbar appears only when I set ListView's 'height' property. But in this case - the size of the table does not depend on the size of the main window. But I need the table to occupy all the free space at the bottom of the window.

1 Answers1

0

I don't know if this will help, but I had a similar issue with just a ListView. The solution I found was to put that ListView into a Container, and expand said Container.

I haven't used the DataTable yet, so I don't know if it will work. If it doesn't, you could try to make the table "manually", by creating each row and adding it as a control of the ListView. It might not be the most elegant solution, but it worked for me.

I know it's not much help, I don't really have a lot of experience using flet and I came across your question while researching something else.