Empty list of ids in a Kivy GridLayout

Question:

I am trying to develop a toy app with Kivy.

So far I have a grid of 9 x 9 TextInput widgets that have been added programmatically to a GridLayout (I refer to it by the id “grid” in my kv file).

For some reason, although I am assigning an id to each of the TextInput widgets, the ids dictionary that I get in the get_widget_from_id is empty.

What am I missing?

main.py

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.textinput import TextInput
from kivy.clock import Clock

class SudokuGame(Widget):
    # Initialize the grid of text inputs
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        grid = self.ids["grid"]
        for i in range(81):
            row = i // 9
            col = i  % 9
            grid.add_widget(TextInput(id = str(row) + "-" + str(col)))

    # Try to retrieve one of the widgets from its id
    def get_widget_from_id(self, *args):
        print(self.ids["grid"].ids)

class SudokuApp(App):
    def build(self):
        game = SudokuGame()
        Clock.schedule_once(game.get_widget_from_id)
        return game

if __name__ == '__main__':
    SudokuApp().run()

sudoku.kv

#:kivy 1.9.1

<TextInput@SudokuGame>:
    text: ""
    font_size: 0.7 * self.width
    padding: 0.3 * self.width, (self.height - self.line_height) / 2
    input_filter: lambda text, from_undo: text if ( 0 < int(text) < 10 and len(self.text) == 0 ) else ""
    multiline: False
    cursor_color: [0, 0, 0, 0]

<SudokuGame>:
    canvas.before:
        Color:
            rgb: 1, 1, 1
        Rectangle:
            pos: self.pos
            size: self.size
    BoxLayout:
        orientation: "vertical"
        size: root.size
        GridLayout:
            id: grid
            rows: 9
            cols: 9
            line_size: 6
            canvas:
                Color:
                    rgb: 0, 0, 0
                Rectangle:
                    pos: self.x + self.width / 3 - self.line_size / 2, self.y
                    size: self.line_size, self.height
                Rectangle:
                    pos: self.x + 2 * self.width / 3 - self.line_size / 2, self.y
                    size: self.line_size, self.height
                Rectangle:
                    pos: self.x, self.y  + self.height / 3 - self.line_size / 2
                    size: self.width, self.line_size
                Rectangle:
                    pos: self.x, self.y  + 2 * self.height / 3 - self.line_size / 2
                    size: self.width, self.line_size
        BoxLayout:
            orientation: "horizontal"
            size_hint: 1, 0.1
            Button:
                text: "Solve"
            Button:
                text: "Clear"
Asked By: Uraza

||

Answers:

The ids dict is populated only from kv ids. The Kivy property that widgets have is actually unrelated, and I’m not sure if it’s used for anything.

Answered By: inclement

Sticking this in there might fix your problems

self.ids = {child.id:child for child in self.children}
Answered By: Lawrence Du

Answer from Lawrence DU did not solve my problem, but spinned my gears.
My problem was solved by this messy code, test it in your situation:

def update_ids(self, **kw):
    def recursion(node, parent):
        parent.ids = {**parent.ids, **node.ids}
        if node.id:
            parent.ids[node.id] = node
        if node.children:
            for child in node.children:
                parent.ids = {**parent.ids, **child.ids}
                recursion(child, parent)
        else:
            pass
for c in self.children:
    recursion(c, self)
Answered By: Maks

Instead use this.

def get_id(self, instance):
    for id, widget in instance.parent.parent.ids.items():
        if widget.__self__ == instance:
            return id
Answered By: le coder
def add_label(self):
    for label_id in range(self._label_count):
        label_widget = MDLabel(
            text="0",
            font_size='44',
            text_color="#fefbff",
        )
        self.root.ids.box_label.add_widget(label_widget)
        self.root.ids[f"label_{label_id}"] = label_widget
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.