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

如何在Python Kivy弹窗中调用RelativeLayout类的方法?

问题描述

点击弹窗按钮尝试调用MainLayout类的print_hello方法时,出现以下错误:

on_press: root.print_hello()
   File "kivy/weakproxy.pyx", line 32, in kivy.weakproxy.WeakProxy.__getattr__
 AttributeError: 'PopupMenu' object has no attribute 'print_hello'

Python文件代码:

#!/usr/bin/env python3

from kivy.app import App
from kivy.factory import Factory
from kivy.uix.relativelayout import RelativeLayout 

class MainLayout(RelativeLayout):
    def __init__(self, **kwargs):
        super(MainLayout, self).__init__(**kwargs)
        self.data = "Important data from the MainLayout class"
    def print_hello(self):
        print("Hello")

class MyApp(App): # defining the app class
    def build(self): # using MyRelativeLayout in the app
        return MainLayout() # returning MyRelativeLayout
    
MyApp().run()

Kv文件代码:

#:import Factory kivy.factory.Factory

<MainLayout>:
    Button:
        text: "Main Button"
        pos_hint: {"x": 0, "top": 1}
        on_press: Factory.PopupMenu().open()
        
<PopupMenu@Popup>
    auto_dismiss: True
    title: "Popup Menu"
    size_hint: [0.80, 0.80]
    pos_hint: {"center_x": 0.5, "center_y": 0.5}
    RelativeLayout:
        size_hint: [1, 1]
        pos_hint: {"x": 0, "top": 1}
        PopupWindowButton:
            id: line_button
            size_hint: [0.10, 0.10 * root.width / root.height]
            pos_hint: {"x": 0, "top": 1}
            text: "Popup Button"
            on_press: root.print_hello()
            
<PopupWindowButton@Button>
    font_size: "15dp"
    background_color: 0, 0.5, 0, 1

需求:通过点击弹窗按钮调用MainLayout类的print_hello方法。

解决方案

方法1:传递MainLayout实例给弹窗

打开弹窗时将当前MainLayout实例传入弹窗,通过引用调用目标方法。

修改Kv文件的MainLayout部分:

<MainLayout>:
    Button:
        text: "Main Button"
        pos_hint: {"x": 0, "top": 1}
        on_press: 
            popup = Factory.PopupMenu()
            popup.main_layout = root  # 传递MainLayout实例
            popup.open()

修改Kv文件的PopupMenu部分:

<PopupMenu@Popup>
    main_layout: None  # 定义属性存储MainLayout实例
    auto_dismiss: True
    title: "Popup Menu"
    size_hint: [0.80, 0.80]
    pos_hint: {"center_x": 0.5, "center_y": 0.5}
    RelativeLayout:
        size_hint: [1, 1]
        pos_hint: {"x": 0, "top": 1}
        PopupWindowButton:
            id: line_button
            size_hint: [0.10, 0.10 * root.width / root.height]
            pos_hint: {"x": 0, "top": 1}
            text: "Popup Button"
            on_press: root.main_layout.print_hello()  # 通过引用调用方法

方法2:通过App实例获取根布局

利用Kivy的app全局变量直接获取根布局(即MainLayout实例),适合全局调用场景。

修改Kv文件的Popup按钮事件:

<PopupMenu@Popup>
    auto_dismiss: True
    title: "Popup Menu"
    size_hint: [0.80, 0.80]
    pos_hint: {"center_x": 0.5, "center_y": 0.5}
    RelativeLayout:
        size_hint: [1, 1]
        pos_hint: {"x": 0, "top": 1}
        PopupWindowButton:
            id: line_button
            size_hint: [0.10, 0.10 * root.width / root.height]
            pos_hint: {"x": 0, "top": 1}
            text: "Popup Button"
            on_press: app.root.print_hello()  # app代表当前App实例,root为根布局

此方法无需修改Python代码,仅调整Kv文件即可。

方法3:Python代码中绑定弹窗事件

在MainLayout类中封装弹窗逻辑,直接绑定按钮事件到目标方法。

修改Python文件的MainLayout类:

class MainLayout(RelativeLayout):
    def __init__(self, **kwargs):
        super(MainLayout, self).__init__(**kwargs)
        self.data = "Important data from the MainLayout class"
    
    def print_hello(self):
        print("Hello")
    
    def open_popup(self):
        popup = Factory.PopupMenu()
        # 绑定按钮点击事件到print_hello方法
        popup.ids.line_button.bind(on_press=lambda x: self.print_hello())
        popup.open()

修改Kv文件的MainLayout按钮事件:

<MainLayout>:
    Button:
        text: "Main Button"
        pos_hint: {"x": 0, "top": 1}
        on_press: root.open_popup()

同时移除PopupMenu中按钮的原有on_press事件:

<PopupMenu@Popup>
    auto_dismiss: True
    title: "Popup Menu"
    size_hint: [0.80, 0.80]
    pos_hint: {"center_x": 0.5, "center_y": 0.5}
    RelativeLayout:
        size_hint: [1, 1]
        pos_hint: {"x": 0, "top": 1}
        PopupWindowButton:
            id: line_button
            size_hint: [0.10, 0.10 * root.width / root.height]
            pos_hint: {"x": 0, "top": 1}
            text: "Popup Button"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 14:17:46