Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clearing and adding data to DataTable without worker will cause it to sometime not display its content. #4928

Closed
kwevin opened this issue Aug 24, 2024 · 9 comments · Fixed by #4992
Assignees
Labels
bug Something isn't working

Comments

@kwevin
Copy link

kwevin commented Aug 24, 2024

Have you checked closed issues? https://github.com/Textualize/textual/issues?q=is%3Aissue+is%3Aclosed

  • Yes

Please give a brief but clear explanation of the issue. If you can, include a complete working example that demonstrates the bug. Check it can run without modifications.

  • When clearing and adding data to DataTable without using a Worker, the DataTable can sometime not properly display its content.

It will be helpful if you run the following command and paste the results:

textual diagnose

Textual Diagnostics

Versions

Name Value
Textual 0.76.0
Rich 13.7.1

Python

Name Value
Version 3.11.1
Implementation CPython
Compiler MSC v.1934 64 bit (AMD64)
Executable C:\Users\Kevin\AppData\Local\pypoetry\Cache\virtualenvs\listentui-qruDwX8r-py3.11\Scripts\python.exe

Operating System

Name Value
System Windows
Release 10
Version 10.0.22621

Terminal

Name Value
Terminal Application Windows Terminal
TERM Not set
COLORTERM Not set
FORCE_COLOR Not set
NO_COLOR Not set

Rich Console options

Name Value
size width=125, height=31
legacy_windows False
min_width 1
max_width 125
is_terminal True
encoding utf-8
max_height 31
justify None
overflow None
no_wrap False
highlight None
markup None
height None
WindowsTerminal_STlEe4HXl2.mp4

mre is large because it contains some data, so it is in a gist https://gist.github.com/kwevin/18a543e54ff7336bb802d711481b1d72

Copy link

We found the following entries in the FAQ which you may find helpful:

Feel free to close this issue if you found an answer in the FAQ. Otherwise, please give us a little time to review.

This is an automated reply, generated by FAQtory

@willmcgugan
Copy link
Collaborator

Could you fix the formatting on the gist?

@TomJGooding
Copy link
Contributor

TomJGooding commented Aug 24, 2024

It looks like the problem is the height=None on this line:

self.table.add_row(*rows, height=None)

This should "auto-detect the optimal height" but seems something isn't quite right.

Here's a more minimal example:

from textual.app import App, ComposeResult
from textual.widgets import DataTable, Input

ROWS = [
    ("lane", "swimmer", "country", "time"),
    (4, "Joseph Schooling", "Singapore", 50.39),
    (2, "Michael Phelps", "United States", 51.14),
    (5, "Chad le Clos", "South Africa", 51.14),
    (6, "László Cseh", "Hungary", 51.14),
    (3, "Li Zhuhao", "China", 51.26),
    (8, "Mehdy Metella", "France", 51.58),
    (7, "Tom Shields", "United States", 51.73),
    (1, "Aleksandr Sadovnikov", "Russia", 51.84),
    (10, "Darren Burns", "Scotland", 51.84),
]


class ExampleApp(App):
    CSS = """
    DataTable {
        border: solid red;
    }
    """

    def compose(self) -> ComposeResult:
        yield Input()
        yield DataTable()

    def on_mount(self) -> None:
        table = self.query_one(DataTable)
        table.add_columns(*ROWS[0])
        self.populate_table()

    def on_input_changed(self) -> None:
        self.populate_table()

    def populate_table(self) -> None:
        table = self.query_one(DataTable)
        table.clear()
        for row in ROWS[1:]:
            table.add_row(
                *row,
                height=None,
            )
        self.log.debug("Table populated")


if __name__ == "__main__":
    app = ExampleApp()
    app.run()

@willmcgugan willmcgugan added the bug Something isn't working label Aug 24, 2024
@willmcgugan
Copy link
Collaborator

Yeah, I concur with @TomJGooding Looks like the auto height is breaking something.

@TomJGooding
Copy link
Contributor

I confess I'm struggling to follow the code, but posting my findings in case it helps someone else fix this bug.

I think the problem is that when the virtual size is calculated, the self._y_offsets is an empty list:

self.virtual_size = Size(
total_width,
self._total_row_height + header_height,
)

@property
def _total_row_height(self) -> int:
"""The total height of all rows within the DataTable"""
return len(self._y_offsets)

Presumably because the row.height is still zero rather than the calculated height here?

for row in self.ordered_rows:
y_offsets += [(row.key, y) for y in range(row.height)]
self._offset_cache[self._update_count] = y_offsets

@mitaa
Copy link

mitaa commented Sep 7, 2024

I have quite a similar issue which might have the same cause.
Not sure if I should open a new issue for that.

When the populate_table method is run for the first time (on startup) everything looks correct.
When it's run for the second time (on_data_table_cell_selected) the auto-width of the columns is incorrect and column widths seem to correspond to the header.

from textual.app import App, ComposeResult
from textual.widgets import DataTable

ROWS = [
    ("lane", "swimmer", "country", "time"),
    (4, "Joseph Schooling", "Singapore", 50.39),
    (2, "Michael Phelps", "United States", 51.14),
    (5, "Chad le Clos", "South Africa", 51.14),
    (6, "László Cseh", "Hungary", 51.14),
    (3, "Li Zhuhao", "China", 51.26),
    (8, "Mehdy Metella", "France", 51.58),
    (7, "Tom Shields", "United States", 51.73),
    (1, "Aleksandr Sadovnikov", "Russia", 51.84),
    (10, "Darren Burns", "Scotland", 51.84),
]


class ExampleApp(App):
    def compose(self) -> ComposeResult:
        yield DataTable()

    def on_mount(self) -> None:
        self.populate_table()

    def on_data_table_cell_selected(self) -> None:
        self.populate_table()

    def populate_table(self) -> None:
        table = self.query_one(DataTable)
        table.clear(columns=True)
        table.add_columns(*ROWS[0])
        table.add_rows(ROWS[1:])
        self.log.debug("Table populated")


if __name__ == "__main__":
    app = ExampleApp()
    app.run()

mitaa added a commit to mitaa/production_planner that referenced this issue Sep 7, 2024
@TomJGooding
Copy link
Contributor

@mitaa This looks like the same issue as #4470?

@mitaa
Copy link

mitaa commented Sep 7, 2024

@TomJGooding You're right! Sorry the confusion.

Copy link

Don't forget to star the repository!

Follow @textualizeio for Textual updates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants