You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kivy报错:'DialogContent'对象无'manager'属性的解决求助

问题描述

点击对话框的“Cancel”或“Save”按钮时触发AttributeError,提示'DialogContent'对象没有'manager'属性。原本想通过root.manager.get_screen('RoutineCreation')调用对应屏幕的close_dialog和add_task方法,结果出错。

报错堆栈

File "kivy_event.pyx", line 727, in kivy._event.EventDispatcher.dispatch
   File "kivy_event.pyx", line 1307, in kivy._event.EventObservers.dispatch
   File "kivy_event.pyx", line 1191, in kivy._event.EventObservers._dispatch
   File "C:\Users\alexa\PycharmProjects\TheFinalApp\venv\lib\site-packages\kivy\lang\builder.py", line 55, in custom_callback
     exec(__kvlang__.co_value, idmap)
   File "C:\Users\alexa\PycharmProjects\TheFinalApp\ardour.kv", line 91, in <module>
     on_release: root.manager.get_screen('RoutineCreation').add_task(task_text, date_text.text), root.manager.get_screen('RoutineCreation').close_dialog()
   File "kivy\weakproxy.pyx", line 32, in kivy.weakproxy.WeakProxy.__getattr__
 AttributeError: 'DialogContent' object has no attribute 'manager'

相关代码

Python代码

from kivymd.app import MDApp
from kivymd.uix.screen import Screen
from kivymd.uix.dialog import MDDialog
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.textfield import MDTextField
from kivymd.uix.button import MDRaisedButton, MDFlatButton
from kivymd.uix.iconbutton import MDIconButton
from kivymd.uix.picker import MDDatePicker
from datetime import datetime

class Ardour(MDApp):
    pass

class RoutineCreation(Screen):

    routine_dialog = None

    def show_routine_dialog(self):
        if not self.routine_dialog:
            self.routine_list_dialog = MDDialog(
                title="Routine Creation",
                type="custom",
                content_cls=DialogContent(),
            )

        self.routine_list_dialog.open()

    def close_dialog(self, *args):
        self.routine_list_dialog.dismiss()

    def add_task(self, task, task_date):
        print(task.text, task_date)
        task.text = ''
    pass

class DialogContent(MDBoxLayout):

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.ids.date_text.text = str(datetime.now().strftime('%A %d %B %Y'))

    def show_date_picker(self):
        date_dialog = MDDatePicker()
        date_dialog.bind(on_save = self.on_save)
        date_dialog.open()

    def on_save(self, instance, value, date_range):
        date = value.strftime('%A %d %B %Y')
        self.ids.date_text.text = str(date)
    pass

KV文件代码

<RoutineCreation>:

    RectTwo:
    OrangeBar:
    OrangeBarTwo:
    Image:
        source: 'image/routinelabel.png'
        size: '300dp', '100dp'
        pos_hint: {'center_x': .5, 'center_y': .88}

    MDList:
        id: the_container

    Button:
        size_hint: None, None
        size: '300dp', '100dp'
        pos_hint: {'center_x': .5, 'center_y': .5}
        on_release: root.manager.get_screen('RoutineCreation').show_routine_dialog()
        background_color: 0, 0, 0, 0
        Image:
            source: 'image/addplan.png'
            center_x: self.parent.center_x
            center_y: self.parent.center_y
            size: self.parent.size

    Button:
        size_hint: None, None
        size: '200dp', '50dp'
        pos_hint: {'center_x': .275, 'center_y':  .125}
        background_color: 0, 0, 0, 0
        on_release:
            app.root.current = 'MenuScreen'
        Image:
            source: 'image/finish.png'
            center_x: self.parent.center_x
            center_y: self.parent.center_y
            size: self.parent.size

    Button:
        size_hint: None, None
        size: '200dp', '50dp'
        pos_hint: {'center_x': .725, 'center_y':  .125}
        background_color: 0, 0, 0, 0
        on_release:
            app.root.current = 'ChoiceScreen'
        Image:
            source: 'image/cancel.png'
            center_x: self.parent.center_x
            center_y: self.parent.center_y
            size: self.parent.size


<DialogContent>:

    orientation: 'vertical'
    spacing: '10dp'
    size_hint: 1, None
    height: '130dp'

    GridLayout:
        rows: 1

        MDTextField:
            id: task_text
            hint_text: 'Add Routine'
            pos_hint: {'center_y': .4}
            max_text_length: 40
            on_text_validate: root.get_screen('RoutineCreation').add_task(task_text, date_text.text)

        MDIconButton:
            icon: 'calendar'
            on_release: root.show_date_picker()
            padding: '10dp'

    MDLabel:
        spacing: '10dp'
        id: date_text

    BoxLayout:
        orientation: 'vertical'
        MDRaisedButton:
            text: 'Save'
            on_release: root.manager.get_screen('RoutineCreation').add_task(task_text, date_text.text), root.manager.get_screen('RoutineCreation').close_dialog()
        MDFlatButton:
            text: 'Cancel'
            on_release: root.manager.get_screen('RoutineCreation').close_dialog()

解决方案

错误核心原因:DialogContent是MDBoxLayout子类,不属于ScreenManager管理的屏幕组件,因此没有manager属性。以下是三种可行解决方式:

方式1:传递父屏幕引用给DialogContent

  1. 修改RoutineCreation的show_routine_dialog方法,将当前屏幕实例传入DialogContent:
def show_routine_dialog(self):
    if not self.routine_dialog:
        self.routine_list_dialog = MDDialog(
            title="Routine Creation",
            type="custom",
            content_cls=DialogContent(parent_screen=self),
        )
    self.routine_list_dialog.open()
  1. 更新DialogContent的初始化方法,保存父屏幕引用:
class DialogContent(MDBoxLayout):
    def __init__(self, parent_screen=None, **kwargs):
        super().__init__(**kwargs)
        self.parent_screen = parent_screen
        self.ids.date_text.text = str(datetime.now().strftime('%A %d %B %Y'))
  1. 修改KV文件中按钮的事件绑定:
# Save按钮
on_release: root.parent_screen.add_task(task_text, date_text.text), root.parent_screen.close_dialog()
# Cancel按钮
on_release: root.parent_screen.close_dialog()
# 文本框回车事件
on_text_validate: root.parent_screen.add_task(task_text, date_text.text)

方式2:通过App实例直接获取ScreenManager

直接在KV文件中使用app.root(需确保App的根组件是ScreenManager)调用目标屏幕方法,无需修改Python代码:

# Save按钮
on_release: app.root.get_screen('RoutineCreation').add_task(task_text, date_text.text), app.root.get_screen('RoutineCreation').close_dialog()
# Cancel按钮
on_release: app.root.get_screen('RoutineCreation').close_dialog()
# 文本框回车事件
on_text_validate: app.root.get_screen('RoutineCreation').add_task(task_text, date_text.text)

方式3:将按钮逻辑绑定到对话框创建时

在RoutineCreation中创建对话框时直接定义按钮,避免跨组件引用:

  1. 修改show_routine_dialog方法:
def show_routine_dialog(self):
    content = DialogContent()
    if not self.routine_dialog:
        self.routine_list_dialog = MDDialog(
            title="Routine Creation",
            type="custom",
            content_cls=content,
            buttons=[
                MDFlatButton(
                    text="CANCEL",
                    on_release=lambda x: self.close_dialog()
                ),
                MDRaisedButton(
                    text="SAVE",
                    on_release=lambda x: (self.add_task(content.ids.task_text, content.ids.date_text.text), self.close_dialog())
                ),
            ],
        )
    self.routine_list_dialog.open()
  1. 删除KV文件中DialogContent内部的按钮布局部分。

内容的提问来源于stack exchange,提问作者Alexander Alico

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 02:05:36