Kivy ScrollView报错:'NoneType'对象无'bind'属性,求修复方案
Hey there! Let's break down what's going wrong here and fix it step by step.
The Root Cause of the AttributeError
Your error happens because when the Controller's __init__ method runs, the layout_content property hasn't been assigned yet. Kivy sets up those object properties after the widget is initialized, so self.layout_content is still None when you try to call .bind() on it.
Fix 1: Move the Binding to a Proper Callback
Instead of putting the bind logic in __init__, use Kivy's built-in property change callback. Add an on_layout_content method to your Controller class—this method will automatically run when layout_content is assigned to the GridLayout from your KV code:
class Controller(FloatLayout): layout_content = ObjectProperty(None) def on_layout_content(self, instance, value): # This runs only after layout_content is linked to the GridLayout value.bind(minimum_height=value.setter('height'))
Fix 2: Tweak ScrollView and GridLayout Settings
Your ScrollView setup is almost right, but let's adjust it to ensure it fills the available space properly. Update the ScrollView in your KV to take all vertical space in the BoxLayout:
ScrollView: size_hint_y: 1 # Make ScrollView fill all available vertical space GridLayout: id: layout_content size_hint_y: None cols: 1 row_default_height: '280dp' # Match your MDCard height for consistency row_force_default: True spacing: 10, 10 padding: 0, 0
Also, the pos_hint on your MDCards will cause alignment issues inside the ScrollView's GridLayout. Remove the pos_hint and adjust the card's size to fit the layout:
MDCard: id: tel1 orientation: "vertical" padding: "8dp" size_hint_x: 1 # Stretch card to fit GridLayout width size_hint_y: None height: "280dp" MDLabel: text: "Tele 1" theme_text_color: "Secondary" size_hint_y: None height: self.texture_size[1] MDSeparator: height: "5dp" MDLabel: text: "Descrizione del primo"
Full Modified Code
Here's the complete working code with all fixes applied:
from kivy.properties import ObjectProperty from kivymd.app import MDApp from kivy.lang import Builder from kivy.uix.floatlayout import FloatLayout KV = """ Screen: Controller: layout_content: layout_content BoxLayout: id: bl orientation: 'vertical' padding: 10, 10 row_default_height: '48dp' row_force_default: True spacing: 10, 10 ScrollView: size_hint_y: 1 GridLayout: id: layout_content size_hint_y: None cols: 1 row_default_height: '280dp' row_force_default: True spacing: 10, 10 padding: 0, 0 MDCard: id: tel1 orientation: "vertical" padding: "8dp" size_hint_x: 1 size_hint_y: None height: "280dp" MDLabel: text: "Tele 1" theme_text_color: "Secondary" size_hint_y: None height: self.texture_size[1] MDSeparator: height: "5dp" MDLabel: text: "Descrizione del primo" MDCard: id: tel2 orientation: "vertical" padding: "8dp" size_hint_x: 1 size_hint_y: None height: "280dp" MDLabel: text: "Tele 2" theme_text_color: "Secondary" size_hint_y: None height: self.texture_size[1] MDSeparator: height: "5dp" MDLabel: text: "Descrizione del secondo" MDCard: id: tel3 orientation: "vertical" padding: "8dp" size_hint_x: 1 size_hint_y: None height: "280dp" MDLabel: text: "Tele 3" theme_text_color: "Secondary" size_hint_y: None height: self.texture_size[1] MDSeparator: height: "5dp" MDLabel: text: "Descrizione del terzo" MDCard: id: tel4 orientation: "vertical" padding: "8dp" size_hint_x: 1 size_hint_y: None height: "280dp" MDLabel: text: "Telefilm 4" theme_text_color: "Secondary" size_hint_y: None height: self.texture_size[1] MDSeparator: height: "5dp" MDLabel: text: "Descrizione del quarto" MDCard: id: tel5 orientation: "vertical" padding: "8dp" size_hint_x: 1 size_hint_y: None height: "280dp" MDLabel: text: "Tele 5" theme_text_color: "Secondary" size_hint_y: None height: self.texture_size[1] MDSeparator: height: "5dp" MDLabel: text: "Descrizione del quinto" """ class Controller(FloatLayout): layout_content = ObjectProperty(None) def on_layout_content(self, instance, value): value.bind(minimum_height=value.setter('height')) class MainApp(MDApp): def build(self): self.title = "LukeFlix" self.theme_cls.theme_style = "Light" self.theme_cls.primary_palette = "Red" return Builder.load_string(KV) MainApp().run()
Why This Works
- The
on_layout_contentcallback ensures we only bind to the GridLayout once it's fully initialized and linked to the property, eliminating theNoneTypeerror. - Setting
size_hint_y: 1on the ScrollView makes it take all available vertical space in the BoxLayout, so scrolling activates when cards exceed the screen height. - Adjusting the MDCard's
size_hint_xremoves alignment issues and ensures cards fit neatly within the scrollable area.
内容的提问来源于stack exchange,提问作者Luca De Filippo




