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

Kivy 2.3.0使用FigureCanvasKivyAgg报错:无'resize_event'属性

解决Kivy 2.3.0中FigureCanvasKivyAgg的AttributeError问题

在Kivy 2.3.0应用中使用FigureCanvasKivyAgg(plt.gcf())绘制基础图表时,持续触发错误:

AttributeError: 'FigureCanvasKivyAgg' object has no attribute 'resize_event'

相关代码及报错信息如下:

matty.py

import kivy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.label import Label
from kivy.lang import Builder
from kivy.metrics import dp, sp
from kivy.clock import Clock

#Graphical Imports
from kivymd.app import MDApp
from kivy.garden.matplotlib.backend_kivyagg import FigureCanvasKivyAgg
import matplotlib.pyplot as plt

x = [ 1, 2, 3, 4, 5]
y = [5, 14, 7, 20, 11]

plt.plot(x,y)
plt.ylabel("y axis")
plt.xlabel("x axis")

class WelcomeScreen(Screen):
    pass

class FirstScreen(Screen):
    pass

class SecondScreen(Screen):
    pass

class ScreenManager(ScreenManager):
    pass

class Graph(FloatLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.add_widget(FigureCanvasKivyAgg(plt.gcf()))

    def save(self):
        pass

class Project(BoxLayout):
    pass

kv = Builder.load_file("matty.kv")

class TestApp(MDApp):
    title = "Kivy Project"

    def build(self, **kwargs):
        return Project()
   
if __name__ == '__main__':
    TestApp().run()

matty.kv

#:kivy 2.3.0
<Project>
    orientation: "vertical"

    canvas.before:
        Color:
            rgb: .6, .6, .6
        Rectangle:
            pos: self.pos
            size: self.size
   
    SomeMenu_ActionBar:
        id: ActionBar

    ScreenManager:
        id: sm
        WelcomeScreen:
        FirstScreen:
        SecondScreen:
            Graph:
                id: graph_screen

<SomeMenu_ActionBar@ActionBar>:

    ActionView:
        id: ActionView

        HiddenIcon_ActionPrevious:

        ActionGroup:
            id: App_ActionGroup
            mode: "spinner"
            text: "Jump to Screen"

            ActionButton:
                text: "Welcome Screen"
                on_release:
                    app.root.ids.sm.current = 'welcome'
                    app.root.ids.sm.transition.direction = "right"
            ActionButton:
                text: "First Screen"
                on_release:
                    app.root.ids.sm.current = 'first'
                    app.root.ids.sm.transition.direction = "left"
            ActionButton:
                text: "Second Screen"
                on_release:
                    app.root.ids.sm.current = 'second'
                    app.root.ids.sm.transition.direction = "left"
       
        ActionGroup:
            id: App_ActionGroup
            mode: 'spinner'
            text: 'App'

            ActionButton:
                text: 'Settings'
                on_press: app.open_settings()
            ActionButton:
                text: 'Quit'
                on_press: app.get_running_app().stop()
       
        ActionGroup:
            id: File_ActionGroup
            mode: 'spinner'
            text: 'File'

            ActionButton:
                text: 'Open'
            ActionButton:
                text: 'Save'
       
        ActionButton:
            text: 'Back to Main Menu'
            on_release:
                app.root.ids.sm.current = 'welcome'
                app.root.ids.sm.transition.direction = "right"

<HiddenIcon_ActionPrevious@ActionPrevious>:
    title: ''
    with_previous: False
    app_icon: ''
    app_icon_width: 0
    app_icon_height: 0
    size_hint_x: None
    width: len(self.title)*10

<WelcomeScreen>:
    name: 'welcome'
    Label:
        text: 'Welcome Screen'
        font_size: sp(50)

<FirstScreen>:
    id: first
    name: 'first'
    Label:
        text: 'First Screen'

<SecondScreen>:
    id: second
    name: 'second'
    Graph:
        id: graph_screen
<Graph>:
    id: boxgraph
    BoxLayout:
        size_hint_y: .9
        pos_hint: {"top": 1}
       
    BoxLayout:
        size_hint_y: .1
        TextInput:
            id: name
            multiline: False

        Button:
            text: "Save"
            on_release: root.save()

报错信息

Traceback (most recent call last):
   File "c:\Users\alisu\OneDrive - UWE Bristol\UWE Bristol & Stuff\3rd Year UWE\Digital Systems\Alistana Fitness & Nutrition Tracker\AFNT-Digital-Systems-Project\AFNT\Application\Classes\matty.py", line 58, in <module>
     TestApp().run()
   File "C:\Users\alisu\OneDrive - UWE Bristol\UWE Bristol & Stuff\3rd Year UWE\Digital Systems\Alistana Fitness & Nutrition Tracker\AFNT-Digital-Systems-Project\AFNT\.venv\Lib\site-packages\kivy\app.py", line 956, in run
     runTouchApp()
   File "C:\Users\alisu\OneDrive - UWE Bristol\UWE Bristol & Stuff\3rd Year UWE\Digital Systems\Alistana Fitness & Nutrition Tracker\AFNT-Digital-Systems-Project\AFNT\.venv\Lib\site-packages\kivy\base.py", line 574, in runTouchApp
     EventLoop.mainloop()
   File "C:\Users\alisu\OneDrive - UWE Bristol\UWE Bristol & Stuff\3rd Year UWE\Digital Systems\Alistana Fitness & Nutrition Tracker\AFNT-Digital-Systems-Project\AFNT\.venv\Lib\site-packages\kivy\base.py", line 339, in mainloop
     self.idle()
   File "C:\Users\alisu\OneDrive - UWE Bristol\UWE Bristol & Stuff\3rd Year UWE\Digital Systems\Alistana Fitness & Nutrition Tracker\AFNT-Digital-Systems-Project\AFNT\.venv\Lib\site-packages\kivy\base.py", line 379, in idle
     Clock.tick()
   File "C:\Users\alisu\OneDrive - UWE Bristol\UWE Bristol & Stuff\3rd Year UWE\Digital Systems\Alistana Fitness & Nutrition Tracker\AFNT-Digital-Systems-Project\AFNT\.venv\Lib\site-packages\kivy\clock.py", line 733, in tick
     self.post_idle(ts, self.idle())
   File "C:\Users\alisu\OneDrive - UWE Bristol\UWE Bristol & Stuff\3rd Year UWE\Digital Systems\Alistana Fitness & Nutrition Tracker\AFNT-Digital-Systems-Project\AFNT\.venv\Lib\site-packages\kivy\clock.py", line 776, in post_idle
     self._process_events()
   File "kivy\_clock.pyx", line 620, in kivy._clock.CyClockBase._process_events
   File "kivy\_clock.pyx", line 653, in kivy._clock.CyClockBase._process_events
   File "kivy\_clock.pyx", line 649, in kivy._clock.CyClockBase._process_events
   File "kivy\_clock.pyx", line 218, in kivy._clock.ClockEvent.tick
   File "C:\Users\alisu\OneDrive - UWE Bristol\UWE Bristol & Stuff\3rd Year UWE\Digital Systems\Alistana Fitness & Nutrition Tracker\AFNT-Digital-Systems-Project\AFNT\.venv\Lib\site-packages\kivy\uix\floatlayout.py", line 97, in do_layout
     c.size = c_w, c_h
     ^^^^^^
   File "kivy\properties.pyx", line 520, in kivy.properties.Property.__set__
   File "kivy\properties.pyx", line 1478, in kivy.properties.ReferenceListProperty.set
   File "kivy\properties.pyx", line 606, in kivy.properties.Property._dispatch
   File "kivy\_event.pyx", line 1307, in kivy._event.EventObservers.dispatch
   File "kivy\_event.pyx", line 1213, in kivy._event.EventObservers._dispatch
   File "C:\Users\alisu\OneDrive - UWE Bristol\UWE Bristol & Stuff\3rd Year UWE\Digital Systems\Alistana Fitness & Nutrition Tracker\AFNT-Digital-Systems-Project\AFNT\.venv\Lib\site-packages\kivy\garden\matplotlib\backend_kivy.py", line 1233, in _on_size_changed
     self.resize_event()
     ^^^^^^^^^^^^^^^^^
AttributeError: 'FigureCanvasKivyAgg' object has no attribute 'resize_event'

解决方案

原因分析

该错误是由于kivy-garden matplotlib库的版本与Kivy 2.3.0不兼容导致的:旧版本的后端代码中调用了resize_event()方法,但在适配Kivy 2.3.0的版本中,该方法已被移除或重命名,且FigureCanvasKivyAgg类不再包含此方法。

修复步骤

方法1:修改代码避免全局Matplotlib状态并适配布局

  1. 移除全局图表代码:把全局的plt.plot等代码移到Graph类内部,创建独立的Figure和Axes,避免全局状态冲突。
  2. 将画布添加到KV定义的布局中:不要直接把画布加到FloatLayout,而是加到KV中预留的BoxLayout容器里。

修改后的matty.py中Graph类:

class Graph(FloatLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # 创建独立的Figure和Axes,不依赖全局plt
        fig, ax = plt.subplots()
        x = [1, 2, 3, 4, 5]
        y = [5, 14, 7, 20, 11]
        ax.plot(x, y)
        ax.set_ylabel("y axis")
        ax.set_xlabel("x axis")
        # 创建画布并添加到KV中指定的容器
        canvas = FigureCanvasKivyAgg(fig)
        self.ids.graph_box.add_widget(canvas)

    def save(self):
        pass

修改matty.kv中的<Graph>规则,给顶部BoxLayout添加id:

<Graph>:
    id: boxgraph
    BoxLayout:
        id: graph_box  # 添加此id用于挂载画布
        size_hint_y: .9
        pos_hint: {"top": 1}
       
    BoxLayout:
        size_hint_y: .1
        TextInput:
            id: name
            multiline: False

        Button:
            text: "Save"
            on_release: root.save()

方法2:修复Kivy Garden Matplotlib后端代码

找到你的虚拟环境中backend_kivy.py文件(路径类似venv/Lib/site-packages/kivy/garden/matplotlib/backend_kivy.py),定位到_on_size_changed方法(大约1233行),将self.resize_event()替换为self.draw():

def _on_size_changed(self, instance, value):
    # 原代码:self.resize_event()
    self.draw()

方法3:更新Kivy Garden Matplotlib到兼容版本

执行命令更新库:

pip install --upgrade kivy-garden
garden install matplotlib --upgrade

内容的提问来源于stack exchange,提问作者alisuhail-amanu2

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 21:34:56