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

Kivy中无法通过id修改Rectangle的source属性的报错求助

问题根因与修复方案

触发报错的核心原因

  • 无效控件实例化:swap()方法中执行Picture().change()时,会生成一个未挂载到界面树的空白Picture对象,该对象未加载对应的kv配置,不存在任何已绑定的组件引用,访问self.ids.rec时必然触发属性不存在的报错。原代码在TileWidget.__init__中已经创建并添加了一个实际展示的Picture实例,但后续逻辑未引用该实例,反而新建了无效对象。
  • canvas指令的id绑定规则:Kivy的ids字典仅自动收集kv规则中定义的、属于控件子节点的UI组件id,直接写在canvas块内的图形指令(如Rectangle)的id,不会自动加入所属控件的ids字典,即便使用正确的已挂载实例,直接访问self.ids.rec也会触发键不存在的错误。

具体修复步骤

  1. 用属性绑定替代id访问
    在Picture类中定义自定义属性,直接将Rectangle的图片源与该属性绑定,修改属性值时自动触发画布重绘,无需手动访问canvas内的节点。
  2. 修正实例引用逻辑
    将TileWidget.__init__中创建的Picture实例存为类成员,swap()方法直接调用该已挂载到界面的实例的切换方法,不再新建无效对象。
  3. 优化计数逻辑
    将原全局计数变量x改为Picture类的内部成员,避免全局变量带来的状态混乱。

修正后的完整代码

Python 代码

from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import StringProperty

class Picture(FloatLayout):
    # 绑定图片源属性,初始值与原配置一致
    source = StringProperty("images.jpg")
    swap_count = 0  # 记录切换次数的内部变量

    def change(self):
        self.swap_count += 1
        if self.swap_count % 2 == 0:
            self.source = "download.jpg"
            print("aaaa")
        else:
            self.source = "images.jpg"
            print("bbbbb")

class TileWidget(FloatLayout):
    def __init__(self, **kwargs):
        super(TileWidget, self).__init__(**kwargs)
        # 保存实际显示的Picture实例引用
        self.pic_widget = Picture()
        self.add_widget(self.pic_widget)

    def swap(self):
        # 直接调用已挂载实例的切换方法
        self.pic_widget.change()

class langApp(App):
    def build(self):
        return TileWidget()

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

KV 配置文件

#:kivy 1.11.1
<TileWidget>:
    FloatLayout:
        pos: 0,0
        size: root.width,root.height
        Button:
            text: 'Last'
            pos_hint: {'x':.25,'y':.1}
            size_hint: .1,.1
        Button:
            text: 'Stop'
            pos_hint: {'x':.45,'y':.1}
            size_hint: .1,.1
        Button:
            on_press: root.swap()
            text: 'Next'
            pos_hint: {'x':.65,'y':.1}
            size_hint: .1,.1

<Picture>:
    pos_hint: {'x':.25,'y':.4}
    canvas:
        Rectangle:
            size: self.size[0]*0.5,self.size[1]*0.5
            pos: self.pos[0],self.pos[1]
            # 直接绑定Picture类的source属性,无需依赖id
            source: root.source

内容的提问来源于stack exchange,提问作者Leon Kardaš

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.24 13:15:01