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

Kivy(Python)实现带图片按钮异常求助

Kivy(Python)实现带图片按钮异常求助

看起来你在尝试用Kivy做两个带自定义图片的可点击按钮,想要分别显示“b1”和“b2”的图片,但目前只看到空白按钮,图片完全没加载出来对吧?我帮你分析下问题,再给你调整方案~

先说说你代码里的核心问题

  1. 图片尺寸获取时机不对:你在build方法里直接获取img01.texture_size,但这时候图片还没加载完成,texture_size大概率是(0,0),导致按钮和图片的尺寸都被设成了0,自然看不到内容。
  2. 重复代码冗余:两个按钮的创建逻辑完全一样,重复写两遍不仅麻烦,还容易出错。
  3. (隐性问题)path1/path2未定义:你代码里直接用了这两个变量但没赋值,运行时会直接报错,这个应该是你写的时候省略了,不过也要注意替换成实际的图片路径~

解决方案1:修复你原有代码的逻辑

我把你的代码重构了一下,主要解决了图片尺寸加载时机的问题,还把重复代码抽成了通用函数,更易维护:

from kivy.app import App
from kivy.uix.image import Image
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.clock import Clock

class MyApp(App):
    def build(self):
        # 替换成你实际的图片路径!
        path1 = "b1.png"
        path2 = "b2.png"
        
        layout = BoxLayout(orientation='horizontal', spacing=10, padding=10)

        # 用通用函数创建带图按钮,避免重复代码
        btn01 = self.create_image_button(path1, self.on_image_click01)
        btn02 = self.create_image_button(path2, self.on_image_click02)

        layout.add_widget(btn01)
        layout.add_widget(btn02)
        return layout

    def create_image_button(self, img_path, click_callback):
        # 创建透明背景的按钮
        btn = Button(size_hint=(None, None), background_normal='', background_down='')
        # 创建图片控件
        img = Image(source=img_path, allow_stretch=True, keep_ratio=False)
        
        # 用Clock延迟执行,等图片加载完成后再设置尺寸
        def set_widget_sizes(dt):
            btn.size = img.texture_size
            img.size = btn.size
        Clock.schedule_once(set_widget_sizes, 0)
        
        btn.add_widget(img)
        btn.bind(on_press=click_callback)
        return btn

    def on_image_click01(self, instance):
        print("Click 1", instance.children[0].source)

    def on_image_click02(self, instance):
        print("Click 2", instance.children[0].source)

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

解决方案2:更简洁的实现方式(推荐)

其实Kivy的Button本身就支持直接把图片设为背景,完全不需要嵌套Image控件,代码会简洁很多:

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout

class MyApp(App):
    def build(self):
        # 替换成你实际的图片路径!
        path1 = "b1.png"
        path2 = "b2.png"
        
        layout = BoxLayout(orientation='horizontal', spacing=10, padding=10)

        # 第一个带图按钮:直接用background_normal设图片
        btn01 = Button(size_hint=(None, None), background_normal=path1, background_down=path1)
        btn01.bind(on_press=self.on_image_click01)
        # 绑定texture_size事件,图片加载完成后自动设置按钮尺寸
        btn01.bind(texture_size=lambda inst, size: setattr(inst, 'size', size))

        # 第二个带图按钮,逻辑和第一个一致
        btn02 = Button(size_hint=(None, None), background_normal=path2, background_down=path2)
        btn02.bind(on_press=self.on_image_click02)
        btn02.bind(texture_size=lambda inst, size: setattr(inst, 'size', size))

        layout.add_widget(btn01)
        layout.add_widget(btn02)
        return layout

    def on_image_click01(self, instance):
        print("Click 1", instance.background_normal)

    def on_image_click02(self, instance):
        print("Click 2", instance.background_normal)

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

这个方案里,background_down可以设置按钮被点击时显示的图片,如果不需要和正常状态不同,直接设成和background_normal一样就行,省了嵌套Image的麻烦~

备注:内容来源于stack exchange,提问作者nel_junior000

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 16:34:38