Kivy问卷App整合ScrollView与DropDown时App.root无效实例错误解决
Kivy问卷App开发问题解决:Invalid instance in App.root错误
问题背景
本人具备Python和SQLite使用经验,目前正在学习Kivy框架并开发问卷App,用于提问并收集数据供后续处理。已通过YouTube教程分别掌握GridLayout、ScrollView、DropDown等组件用法,现尝试整合实现问卷功能,完整代码如下:
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()
期望App运行后显示含标题、标签、文本输入框、下拉菜单、提交按钮的窗口并具备滚动功能,但运行时出现错误:
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
单独使用ScrollView功能正常,移除滚动功能时仅显示下拉按钮,请问该如何解决?
错误原因分析
- App.build()返回值错误:Kivy要求
build()方法只能返回一个Widget实例作为应用的根组件,当前代码返回了self.root(ScrollView)和self.main(下拉按钮)组成的元组,这直接触发了Invalid instance in App.root错误。 - 下拉按钮未添加到布局:
self.main按钮没有被添加到GridLayout中,所以移除滚动功能返回self.main时,只会显示这个按钮,其他控件都无法在界面上展示。
修复后的完整代码
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.layout.add_widget(self.main) # 添加提交按钮 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, 1)) self.root.add_widget(self.layout) # 只返回滚动视图作为根组件 return self.root def select_text(self, instance, x): self.main.text = x def submit(self, obj): teach_code = self.code_in.text # 可扩展为保存到SQLite的逻辑 print(f"提交的代码: {teach_code}, 下拉选择项: {self.main.text}") if __name__ == '__main__': QuestionnaireApp().run()
关键修改点
- 修正返回值:
build()方法仅返回self.root(ScrollView实例),符合Kivy对根组件的要求。 - 添加下拉按钮到布局:调用
self.layout.add_widget(self.main),让下拉按钮显示在界面的正确位置。 - 优化ScrollView配置:将
size_hint设置为(1,1),让滚动视图自动适配窗口大小,无需手动指定固定尺寸。 - 补充提交逻辑示例:在
submit方法中添加打印语句,方便测试数据收集功能,后续可扩展为SQLite存储逻辑。
内容的提问来源于stack exchange,提问作者lt59
相关产品推荐
相关产品推荐

