kivykivymd

Why is my dynamic Kivy MDDataTable only being created with max 5 rows?


I'm creating a simple scorecard app. My MDDataTable is created dynamically upon the click of a button from a previous screen.

It works correctly when I the value of rounds is 5 or less, however as soon as the value of it is anything above 5, only 5 rows are created.

The below should be a minimum reproducable example:

from kivy.lang import Builder

from kivymd.app import MDApp
from kivymd.uix.list import OneLineListItem
from kivymd.uix.datatables import MDDataTable
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.metrics import dp


KV = '''
<NewGameWindow>:
    name: "new_game"

    MDBoxLayout:
        orientation: "vertical"
        
        MDTopAppBar:
            id: nav_bar
            title: "New Game"
            md_bg_color: app.theme_cls.primary_color
            left_action_items: [['close', lambda x: app.close()]]
            right_action_items: [['content-save-outline']]
        
        MDBoxLayout:
            orientation: "vertical"
            
            MDTextField:
                mode: "line"
                text: "New Game"
                pos_hint: {"center_x": 0.5}
                size_hint_x: 0.75

            MDLabel:
                text: "Number of Rounds:"
                size_hint_y: 0.1
                halign: "center"
                
            MDSlider:
                id: rounds
                step: 1
                value: 10
                track_color_active: app.theme_cls.primary_color
                size_hint_y: 0.1
                size_hint_x: 0.75
                pos_hint: {"center_x": 0.5}
                
            MDLabel:
                text: "Number of Players:"
                size_hint_y: 0.1
                halign: "center"
                
            MDSlider:
                id: players
                step: 1
                value: 10
                track_color_active: app.theme_cls.primary_color
                size_hint_y: 0.1
                size_hint_x: 0.75
                pos_hint: {"center_x": 0.5}
                
            Button:
                on_press: app.create_table()
       
<ScorecardWindow>:
    name: "scorecard"
     
    MDBoxLayout:
        orientation: "vertical"
        
        MDTopAppBar:
            id: nav_bar
            title: "Scorecard"
            md_bg_color: app.theme_cls.primary_color
        
        MDScrollView:
            id: add_table_to_scrollview
        
'''


class LandingWindow(Screen):
    pass


class NewGameWindow(Screen):
    pass


class ScorecardWindow(Screen):
    pass


class WindowManager(ScreenManager):
    pass
class Example(MDApp):

    def build(self):
        kv = Builder.load_string(KV)
        self.theme_cls.theme_style = "Light"
        self.sm = WindowManager()

        screens = [NewGameWindow(name="new_game"), ScorecardWindow(name="scorecard"),]
        for screen in screens:
            self.sm.add_widget(screen)

        self.sm.current = "new_game"
        return self.sm


    def create_table(self):
        rounds = self.root.get_screen("new_game").ids['rounds'].value
        players = self.root.get_screen("new_game").ids['players'].value
        players = int(players)
        rounds = int(rounds)
        print(players)
        print(rounds)
        round_list = [("0",) * players for _ in range(rounds)]
        print(round_list)
        table = MDDataTable(
            column_data=[(f"Player {x + 1}", dp(20)) for x in range(players)],
            row_data=round_list,
            on_row_press = self.open_popup
        )

        table.bind(on_row_press=self.open_popup)
        self.root.get_screen("scorecard").ids['add_table_to_scrollview'].add_widget(table)
        self.sm.current = "scorecard"

Solution

  • By default, MDDataTable assumes 5 rows. You need to specify the actual number of rows using rows_num. Try this:

        table = MDDataTable(
            rows_num=len(round_list),
            column_data=[(f"Player {x + 1}", dp(20)) for x in range(players)],
            row_data=round_list,
            on_row_press = self.open_popup
        )
    

    You can also use pagination instead of a ScrollView with the default number of rows at 5. See the documentation.