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
相关产品推荐
相关产品推荐

