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

Kivy框架Image组件自动缩放问题:如何保留原始图片尺寸?

问题分析与解决办法

问题根源

  1. 父容器尺寸约束:CharWidget继承自Widget,默认尺寸为(100, 100),而Image组件默认的size_hint=(1,1)会让它自动填满父容器,导致图片被强制缩放到100x100的尺寸。
  2. 异步加载时机问题:在__init__里直接设置self.png.size = self.png.texture_size无效,因为Kivy加载图片纹理是异步操作,此时纹理还未加载完成,texture_size仍为默认的(0, 0)。

解决步骤

1. 解除Image的size_hint约束

给Image设置size_hint=(None, None),让它脱离父容器的尺寸限制,能自由设置自身大小:

self.png = Image(source=self.path, size_hint=(None, None))

2. 监听纹理加载完成事件,设置原始尺寸

通过绑定on_texture事件,等图片纹理加载完成后再将size设为texture_size:

self.png.bind(on_texture=self.set_image_size)

# 新增尺寸设置方法
def set_image_size(self, instance, value):
    instance.size = instance.texture_size

3. 同步父容器尺寸(可选)

如果需要CharWidget跟随图片尺寸变化,可在set_image_size方法中同步更新自身尺寸:

def set_image_size(self, instance, value):
    instance.size = instance.texture_size
    self.size = instance.texture_size  # 让父容器与图片尺寸一致

修改后的完整代码

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.image import Image
from kivy.graphics import Color, Rectangle
# 导入你的Char类
from your_module import Char

class CharWidget(Widget):
    def __init__(self, **kwargs):
        self.glyph = kwargs.pop("glyph")
        super().__init__(**kwargs)  # 用super调用父类构造,更规范
        self.path = "/tmp/satie.png"
        self.png = Image(source=self.path, size_hint=(None, None))
        self.png.bind(on_texture=self.set_image_size)
        self.add_widget(self.png)

    def set_image_size(self, instance, value):
        instance.size = instance.texture_size
        self.size = instance.texture_size  # 可选:同步父容器尺寸

    def on_touch_down(self, touch):
        self.png.pos = (touch.x, touch.y)
        with self.canvas:
            Color(1, 0, 0, .5)
            Rectangle(pos=self.png.pos, size=(self.glyph["width"], self.glyph["height"]))

class SatieApp(App):
    def build(self):
        parent = Widget()
        parent.add_widget(CharWidget(glyph=Char(name="clefs.G", font="haydn").glyph))
        return parent

if __name__ == "__main__":
    SatieApp().run()

额外说明

  • 原代码中SatieApp.build()里的with parent.canvas: Color(1,0,0)无实际作用,因为该颜色指令仅影响parent画布后续绘制的图形,而添加的CharWidget有独立画布,可直接删除。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 23:45:40