Search code examples
pythonkivyscrollviewdropdown

I keep getting error of invalid instance in app.root when trying to run the .py file of kivy.It doesnt work when i have both scrollview and dropdown


I have had some experience with Python and SQLite and I'm currently learning Kivy as I'm doing a project. I want to write a questionnaire app to ask questions and collect data from it to work with later on. I followed tutorials on youtube on separated parts like GridLayout, ScrollView, DropDown, etc. and am trying to put them together to produce a questionnaire. Below is my code in full.

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.dropdown import DropDown
from kivy.lang import Builder
from kivy.uix.scrollview import ScrollView
from kivy.core.window import Window

Builder.load_string("""
<CustomDropDown>
    Button:
        text: "1st item"
        size_hint_y: None
        height: 30
        on_release: root.select("1st item")
    Button:
        text: "2nd item"
        size_hint_y: None
        height: 30
        on_release: root.select("2nd item")
    Button:
        text: "3rd item"
        size_hint_y: None
        height: 30
        on_release: root.select("3rd item")
    Button:
        text: "4th item"
        size_hint_y: None
        height: 30
        on_release: root.select("4th item")
""")

class CustomDropDown(DropDown):
    pass

class QuestionnaireApp(App):

    def build(self):
        self.layout = GridLayout(cols = 1, spacing = 10, size_hint_y = None, padding = (200,50))
        self.layout.bind(minimum_height = self.layout.setter("height"))

        Window.clearcolor = (1,1,1,1)

        self.ttl = Label(text = "Title",
                          height = 50,
                          font_size = 24,
                          color = "black")
        self.layout.add_widget(self.ttl)

        self.code_ask = Label(text = "Code?", size_hint_y = None,
                              height = 30, color = "black")
        self.layout.add_widget(self.code_ask)

        self.code_in = TextInput(size_hint_y = None, height = 30)
        self.layout.add_widget(self.code_in)

        self.main = Button(text = "Select item", size_hint_y = None, height = 30)
        dropdown = CustomDropDown()
        self.main.bind(on_release = dropdown.open)
        dropdown.bind(on_select = self.select_text)

        self.click = Button(text = "Submit", size_hint_y = None, height = 30, on_release = self.submit)
        self.layout.add_widget(self.click)
        
        self.root = ScrollView(size_hint = (1, None), size = (Window.width, Window.height))
        self.root.add_widget(self.layout)

        return self.root, self.main
    
    def select_text(self, instance, x):
        self.main.text = x

    def submit(self, obj):
        teach_code = self.code_in.text

if __name__ == '__main__':`
    QuestionnaireApp().run()

I want the app to run and produce a window with a heading, a label, a text input box, a dropdown, and a button with a scrolling function. However, when I run this code it produces an error like this:

Exception has occurred: Exception
Invalid instance in App.root
  File "C:\...\try.py", line 79, in <module>
    QuestionnaireApp().run()
Exception: Invalid instance in App.root

When I run it without the dropdown, everything works just fine. When I run the code without the scrolling function, only the dropdown shows up and not any other.

How do I fix this?


Solution

  • The build() method of an App must return a single widget that becomes the root of your App display. Your build() method returns a tuple of two widgets, which will not work. Try adding:

        self.layout.add_widget(self.main)
    

    to your build() method, and change the return to:

    return self.root