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

KivyMD中ThreeLineAvatarListItem加载URL图片报Not found错误如何解决

解决方案

KivyMD默认的ImageLeftWidget原生仅支持本地图片路径加载,直接传入网络URL会触发资源找不到的报错,你可以通过以下两种方案实现网络图片加载需求:

方案1:搭配Kivy原生AsyncImage组件

AsyncImage是Kivy内置支持异步加载网络图片的组件,你可以直接替换ImageLeftWidget使用,调整代码如下:

from kivy.uix.image import AsyncImage

for row in result:
    # 用AsyncImage异步加载网络图片,设置合适的尺寸适配列表项
    image = AsyncImage(
        source=row[3],
        size_hint=(None, None),
        size=("40dp", "40dp"),
        pos_hint={"center_y": 0.5}
    )
    items = ThreeLineAvatarListItem(
        text=row[0], 
        secondary_text=row[1],
        tertiary_text=row[2]
    )
    items.add_widget(image)
    lv.add_widget(items)

如果需要圆形头像效果,可以给AsyncImage套一层裁剪画布:

from kivy.graphics import Color, Ellipse, StencilPush, StencilUse, StencilPop, StencilUnUse
from kivy.uix.image import AsyncImage

class RoundAsyncImage(AsyncImage):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.bind(pos=self.update_canvas, size=self.update_canvas)

    def update_canvas(self, *args):
        self.canvas.before.clear()
        with self.canvas.before:
            StencilPush()
            Ellipse(pos=self.pos, size=self.size)
            StencilUse()
        with self.canvas.after:
            StencilUnUse()
            StencilPop()

之后直接用RoundAsyncImage替换上面的AsyncImage即可。

方案2:先下载网络图片到本地缓存再加载

如果需要复用图片避免重复请求,可以先把网络图片下载到本地缓存目录,再把本地路径传给ImageLeftWidget使用,示例逻辑如下:

import os
import requests
from kivymd.utils import app_path

def get_cached_image(url):
    # 生成缓存文件名,取URL最后一段作为文件名
    cache_dir = os.path.join(app_path, "image_cache")
    os.makedirs(cache_dir, exist_ok=True)
    file_name = url.split("/")[-1].split("?")[0] + ".jpg"
    cache_path = os.path.join(cache_dir, file_name)
    # 缓存存在直接返回本地路径
    if os.path.exists(cache_path):
        return cache_path
    # 缓存不存在下载到本地
    resp = requests.get(url, timeout=10)
    if resp.status_code == 200:
        with open(cache_path, "wb") as f:
            f.write(resp.content)
        return cache_path
    return ""

# 业务代码调整
for row in result:
    local_img_path = get_cached_image(row[3])
    if local_img_path:
        image = ImageLeftWidget(source=local_img_path)
    else:
        # 加载失败时用默认占位图
        image = ImageLeftWidget(source="assets/default_avatar.png")
    items = ThreeLineAvatarListItem(text=row[0], secondary_text=row[1],tertiary_text=row[2])
    items.add_widget(image)
    lv.add_widget(items)

注意:使用requests下载的场景如果是大量图片,建议放到异步线程执行避免阻塞UI。

内容的提问来源于stack exchange,提问作者Michaël

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 02:24:06