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

Kivy嵌套布局中按钮调用父类方法报错问题咨询

Kivy按钮调用方法报错问题解决

问题描述

我在info_options.kv的StackLayout中创建了一个按钮,希望点击时调用InfoOptionsPanel类的on_press方法。直接让App返回InfoOptionsPanel()时功能正常,但改用MainPanel作为GUI根组件后,点击按钮会抛出AttributeError,不过GUI显示正常。

报错信息

File "C:\Users\..\AppData\Local\Programs\Python\Python312\Lib\site-packages\kivy\lang\builder.py", line 60, in custom_callback
     exec(__kvlang__.co_value, idmap)
   File "K:\path\to\project\Info_options.kv", line 5, in <module>
     on_press: self.parent.on_press()
 ^^^^^^^^^^^^^^^^
 AttributeError: 'InfoOptionsPanel' object has no attribute 'on_press'

相关文件内容

info.kv

<InfoPanel@BoxLayout>
    orientation: 'vertical'
    size_hint_y: 0.8
    pos_hint: {"top": 1}
    Label:
        id: info_label
        text:"Click button"
        font_size:50

info_options.kv

<InfoOptionsPanel@StackLayout>:
    orientation: 'lr-tb'
    Button:
        text: 'Button'
        on_press: self.parent.on_press()
        size_hint :.7, 0.1

main_screen.kv

<MainPanel@BoxLayout>:
    orientation: 'vertical'
    
    AnchorLayout:
        anchor_x: 'left'
        anchor_y: 'top'
        InfoPanel:
            size: 100, 100

    AnchorLayout:
        anchor_x: 'right'
        anchor_y: 'bottom'
        InfoOptionsPanel:
            size: 100, 100

main.py

from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.stacklayout import StackLayout
import os

kivy_design_files = ["Info_options", "Info", "main_screen",]
for kv_file in kivy_design_files:
    Builder.load_file(os.path.join(os.path.abspath(os.getcwd()), kv_file + ".kv"))
    
class InfoPanel(BoxLayout):
    pass

class InfoOptionsPanel(StackLayout):
    def on_press(self):
        print("Button pressed\n"*55)

class MainPanel(BoxLayout):
    pass

class MyApp(App):
    def build(self):
        return MainPanel()

if __name__ == '__main__':
    MyApp().run()

解决方案

问题根源在于KV文件中使用@符号创建的类与Python代码中定义的同名类冲突:

  1. 在KV文件中,<ClassName@Widget>语法是直接创建一个继承自对应组件的新类;而你已经在Python代码中定义了同名的InfoOptionsPanel和InfoPanel类,此时KV创建的类会覆盖Python中的类,导致实例化的组件没有Python类中定义的on_press方法。

  2. 解决步骤:

    • 修改info_options.kv,将类定义从<InfoOptionsPanel@StackLayout>改为<InfoOptionsPanel>:
      <InfoOptionsPanel>:
          orientation: 'lr-tb'
          Button:
              text: 'Button'
              on_press: self.parent.on_press()
              size_hint :.7, 0.1
      
    • 同理修改info.kv,将<InfoPanel@BoxLayout>改为<InfoPanel>:
      <InfoPanel>:
          orientation: 'vertical'
          size_hint_y: 0.8
          pos_hint: {"top": 1}
          Label:
              id: info_label
              text:"Click button"
              font_size:50
      
    • main_screen.kv中的<MainPanel@BoxLayout>可以保留,因为Python中的MainPanel类没有额外方法,或者也可以改为<MainPanel>保持规则统一。

修改后,KV文件会直接为Python中已定义的类应用布局规则,此时点击按钮就能正常调用InfoOptionsPanel的on_press方法了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 13:12:33