You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Kivy ScrollView报错:'NoneType'对象无'bind'属性,求修复方案

Fixing AttributeError and ScrollView Issues in Kivy/KivyMD Card Layout

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_content callback ensures we only bind to the GridLayout once it's fully initialized and linked to the property, eliminating the NoneType error.
  • Setting size_hint_y: 1 on 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_x removes alignment issues and ensures cards fit neatly within the scrollable area.

内容的提问来源于stack exchange,提问作者Luca De Filippo

火山引擎 最新活动