Referencing Layout from a different class kivy

Viewed 30

EDIT: so this is a very simple version of what it is like in my app but i think you get the point. Basically i want to destroy the Buttons created in the for loop with the Button on the destroywidgets screen.

.kv:

 MainWindow:

<MainWindow>

    FloatLayout:
        size_hint: 1, .1

        Button:
            text:"next screen"
            size_hint:.1,1
            pos_hint:{"x": 0, "y": 0}
            on_release: app.root.current = "destroywidgets"

        Button:
            text:"laodwidgets"
            on_release: root.create_widgets()
            size_hint:.1, 1
            pos_hint:{"x": .5, "y": 0}

.py:

from kivy.app import App
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.scrollview import ScrollView


class MainWindow(Screen):
    name = "mainwindow"

    def __init__(self, **kwargs):
        super(MainWindow, self).__init__()

        self.scrl_view_1 = ScrollView(
            size_hint_y=.85,
            pos_hint={"x": 0, "y": .15},
            do_scroll_x=False,
            do_scroll_y=True,
            size_hint_x=1
        )

        self.scrl_child_1 = GridLayout(
            size_hint_x=1,
            size_hint_y=None,
            cols=2,
            height=1000,
            row_default_height=150,
            row_force_default=True
        )

        self.add_widget(self.scrl_view_1)
        self.scrl_view_1.add_widget(self.scrl_child_1)

    def create_widgets(self):

        print("creating widgets")

        for i in range(0, 6):

            btn = Button(
                text=str(i)
            )

            self.scrl_child_1.add_widget(btn)

            print("added")


class DestroyWidgets(Screen):
    name = "destroywidgets"

    def __init__(self, **kwargs):
        super(DestroyWidgets, self).__init__()

        btn_destroy_widgets = Button(
            text="Destroy children of Mainwindow",
            #some on release function to clear all children from scrl_child_1 in Mainwindow
        )

        self.add_widget(btn_destroy_widgets)


class ShoppingList(App):

    def build(self):

        self.sm = ScreenManager()
        self.sm.add_widget(MainWindow(name="mainwindow"))
        self.sm.add_widget(DestroyWidgets(name="destroywidgets"))

        return self.sm

if __name__ == "__main__":
    main_app = ShoppingList()
    main_app.run()

So I have to reference a GridLayout which is inside of a ScrollView created in class A in class B. Since you cannot give Layouts an ID in python code and reference it with self.ids i can't figure out how to do it. I tried suggestions from another post with the weakref.ref method as example but i couldn't get it to work. The whole point is that i have to destroy all children of Layouts from other classes in a function somehow.

Heres just a little snippet of my code which i think will be enough. If you need more just write me. Thanks for all the help in advance!

class SelfMadePlans(Screen):
name = "selfmadeplans"

def __init__(self, **kwargs):
    super(SelfMadePlans, self).__init__()

    self.scrl_view_2 = ScrollView(
        size_hint_y=.85,
        pos_hint={"x": 0, "y": 0},
        do_scroll_x=False,
        do_scroll_y=True,
        size_hint_x=1
    )

    self.scrl_child_2 = GridLayout(
        size_hint_x=1,
        size_hint_y=None,
        cols=3,
        height=20000,
        row_default_height=150,
        row_force_default=True,
    )

    self.add_widget(self.scrl_view_2)
    self.scrl_view_2.add_widget(self.scrl_child_2)

and then something in another class like:

class B:

    def destroy_children(self):

        MDApp.get_running_app().sm.get_screen("selfmadeplans").ids.scrl_child_2.children.clear()
1 Answers

First of all you must pass var. no. of kwargs in __init__ in order to use and get all the default functionalities.

...
    def __init__(self, **kwargs):
        super(MainWindow, self).__init__(**kwargs)
...

etc.

Next to access certain screen from ScreenManager you can use method get_screen as follows,

...
        btn_destroy_widgets = Button(
            text="Destroy children of Mainwindow",
            #some on release function to clear all children from scrl_child_1 in Mainwindow
        )
        btn_destroy_widgets.bind(on_release = self.destroy_widgets_on_main)

        self.add_widget(btn_destroy_widgets)

    def destroy_widgets_on_main(self, *args):
        main_window = self.manager.get_screen("mainwindow")
        main_window.scrl_child_1.clear_widgets()

Related