Adding variable number of controls to DropDown - weakly-referenced object no longer exists
<p>I have a dropdown with a list of the months in it. When the Month is selected, I'm trying to dynamically populate buttons in a second dropdown with the correct number of days. When I do so, I get:</p>

<pre><code>ReferenceError: weakly-referenced object no longer exists
</code></pre>

<p>Here are my files for reference:</p>

<p>main.py:</p>

<pre><code>from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button

globIDs = {}

class appScreen(BoxLayout):

    def dayDropPop(self, num):
        globIDs['dayDropDown'].populate(num)


class ExtDropDown(BoxLayout):
    heldValue = ''

    def setID(self, key):
        globIDs[key] = self

    def changeValue(self, sentText, parent):
        self.heldValue = sentText
        parent.text = sentText

class PriorityDropDown(ExtDropDown):
    pass

class MonthDropDown(ExtDropDown):

    def __init__(self, **kwargs):
        super(MonthDropDown, self).__init__(**kwargs)
        self.setID('monthDropDown')

    def monthSelect(self, month):
        monthDay = {'Jan': 31, 'Feb': 29, 'Mar': 31, 'Apr': 30, 'May': 31, 'Jun': 30, 'Jul': 31, 'Aug': 31, 'Sep': 30,
                    'Oct': 31, 'Nov': 30, 'Dec': 31}

        numOfDays = monthDay[month]
        appScreen().dayDropPop(numOfDays)

    def testingFurther(self):
        print()

class DayDropDown(ExtDropDown):

    def __init__(self, **kwargs):
        super(DayDropDown, self).__init__(**kwargs)
        self.setID('dayDropDown')

    def populate(self, num):

        for i in range(0, num):
            newButt = Button(text=str(num + 1))
            self.ids.drop.add_widget(newButt)

class schedulerApp(App):

    def build(self):
        return appScreen()

if __name__ == '__main__':
    schedulerApp().run()
</code></pre>

<p>scheduler.kv:</p>

<pre><code>&lt;PriorityDropDown&gt;:
    Button:
        id: ddRoot
        text: 'Priority'
        on_release: drop.open(ddRoot)
        size_hint_y: None
        height: root.height

    DropDown:
        id: drop
        on_parent: self.dismiss()
        on_select: root.changeValue(args[1], ddRoot)

        Button:
            text: 'Top'
            size_hint_y: None
            height: root.height
            on_release: drop.select(self.text)
        Button:
            text: 'High'
            size_hint_y: None
            height: root.height
            on_release: drop.select(self.text)
        Button:
            text: 'Medium'
            size_hint_y: None
            height: root.height
            on_release: drop.select(self.text)
        Button:
            text: 'Low'
            size_hint_y: None
            height: root.height
            on_release: drop.select(self.text)

&lt;MonthDropDown&gt;:
    Button:
        id: ddRoot
        text: 'Month'
        on_release: drop.open(ddRoot)
        size_hint_y: None
        height: root.height

    DropDown:
        id: drop
        on_parent: self.dismiss()
        on_select: root.monthSelect(args[1])

        Button:
            text: 'Jan'
            size_hint_y: None
            height: root.height
            on_release: drop.select(self.text)
        Button:
            text: 'Feb'
            size_hint_y: None
            height: root.height
            on_release: drop.select(self.text)
        Button:
            text: 'Mar'
            size_hint_y: None
            height: root.height
            on_release: drop.select(self.text)
        Button:
            text: 'Apr'
            size_hint_y: None
            height: root.height
            on_release: drop.select(self.text)
        Button:
            text: 'May'
            size_hint_y: None
            height: root.height
            on_release: drop.select(self.text)
        Button:
            text: 'Jun'
            size_hint_y: None
            height: root.height
            on_release: drop.select(self.text)
        Button:
            text: 'Jul'
            size_hint_y: None
            height: root.height
            on_release: drop.select(self.text)
        Button:
            text: 'Aug'
            size_hint_y: None
            height: root.height
            on_release: drop.select(self.text)
        Button:
            text: 'Sep'
            size_hint_y: None
            height: root.height
            on_release: drop.select(self.text)
        Button:
            text: 'Oct'
            size_hint_y: None
            height: root.height
            on_release: drop.select(self.text)
        Button:
            text: 'Nov'
            size_hint_y: None
            height: root.height
            on_release: drop.select(self.text)
        Button:
            text: 'Dec'
            size_hint_y: None
            height: root.height
            on_release: drop.select(self.text)

&lt;DayDropDown&gt;:
    height: root.height
    Button:
        id: ddRoot
        text: 'Day'
        on_release: drop.open(ddRoot)
        size_hint_y: None
        height: root.height

    DropDown:
        id: drop
        on_parent: self.dismiss()
        on_select: root.changeValue(args[1], ddRoot)

&lt;appScreen&gt;:
    orientation: 'vertical'
    Label:
        size_hint_y: .1
        text: 'Hello World'
    GridLayout:
        size_hint_y:.1
        width: root.width
        cols: 3
        Button:
        Button:
        Button:
    ScrollView:
        canvas.before:
            Color:
                rgba: .3, .3, .3, 5
            Rectangle:
                pos: self.pos
                size: self.size
        GridLayout:
            cols: 3
            Label:
                id: textReceiver
                text: 'Words'
                text_size: self.size
                halign: 'left'
                valign: 'top'
            Label:
            Label:
    BoxLayout:
        size_hint_y: .125
        TextInput:
            size_hint_x: .7
        PriorityDropDown:
            size_hint_x: .3
    BoxLayout:
        size_hint_y: .125
        MonthDropDown:
            size_hint_x: .35
        DayDropDown:
            id: 'dayDrop'
            size_hint_y: 1
            size_hint_x: .2
        TextInput:
            size_hint_x: .45
</code></pre>

<p>I think the issue stems from the controls in question being created in Kivy code, rather than in Python. What testing I've done leads me to believe that I'm referencing my DayDropDown widget incorrectly. However, I don't know how else I would do so. With that in mind, how would I go about referencing my DayDropDown using what I already have? If that isn't my issue, what else might be causing the ReferenceError to be thrown?</p>

<p><strong>Edit:</strong></p>

<p>Messed with my code a little bit. I created a new class "globAddable" with methods "getID" - a simple return self - and put setID in there instead. I then set my  setID now assigns self.getID() to a variable, then uses that variable as the object to be added to the globObjects (formerly globIDs) dictionary.</p>

<p>I also created a new class for my DropDown object, called ExtDropArray, which lives in my DayDropDown. I moved the populate() method to this new class so that it can be called directly by the Dropdown, rather than its parent BoxLayout. I made the ExtDropArray and ExtDropDown inherit from globAddable to expose the setID (and implicitly getID) methods.</p>

<p>The net result of all this is exactly the same. I still don't see my day DropDown when clicking the button on DayDropDown, and after testing with different values on the MonthDropDown, again I get the 'ReferenceError: weakly-referenced object no longer exists' error. However, I am noticing that the offending line is actually the method that opens the dropdown (drop.open(ddRoot), which is called on line 114 of my .kv file). This still doesn't quite give me enough information to know which part of the process is causing the error, be it the adding of the buttons to the DropDown or simply the calling of the open method. Given this new information, is anyone able to deduce what needs to change?</p>

<p>Alright, I finally figured this one out.</p>

<p>My ReferenceError was not a result of my methods, but rather a fundamental misunderstanding on my part of the implementation of DropDown objects. The fix was simply </p>

<pre><code>&lt;DayDropDown&gt;:
    drop: drop.__self__
    ...
</code></pre>

<p>This took me one heck of a long time to find, but came in the form of <a href="https://media.readthedocs.org/pdf/kivy/latest/kivy.pdf" rel="nofollow">this</a> documentation. Seeing as no other posts mentioning these ReferenceErrors makes any mention to this document, I'm leaving it here for others to use in case they run into a similar issue.</p>

python kivy