Kivy拖动滑动条保存图片后界面未重绘问题求助
问题排查与修复方案
核心问题原因
- Kivy的
Image组件默认会缓存已加载的图片资源,你虽然更新了本地TestImage.png文件的内容,但组件不会主动检测文件变更,仍然显示缓存的旧图片。 - 每次滑动条回调时都会往根布局画布中新增一个
ImageKv实例,旧的图片组件没有被清理,始终叠在层级上方遮挡新内容。 - 画布中添加的
Color指令是全局生效的,会对后续所有绘图元素造成不必要的色彩偏移,此处加载图片完全不需要额外加颜色指令。
修复步骤
- 把
ImageKv实例作为App的属性保存,仅在第一次点击OK时创建,后续不再重复生成 - 每次更新图片文件后,调用
ImageKv实例的reload()方法刷新缓存,触发重绘 - 移除
view_image方法中多余的Color指令
修复后完整代码
from kivy.core.window import Window from kivy.app import App from kivy.uix.relativelayout import RelativeLayout from kivy.uix.button import Button from kivy.uix.image import Image as ImageKv from kivy.uix.slider import Slider from PIL import Image, ImageDraw class View(): # 新增参数接收已存在的ImageKv实例,没有的话就创建 def view_image(self, size, pos, canvas, filename, img_widget=None): if not img_widget: rect = ImageKv(source=filename,pos=pos, size=size ) with canvas: canvas.add(rect) return rect else: img_widget.source = filename img_widget.reload() return img_widget class MainApp(App): def OnAzmSliderValueChange(self, instance,value): if self.image != None: self.photo.polygon(self.polygon, fill = 'green') self.image.save(self.img_name) # 传入已有的img_widget更新内容 self.img_widget = self.view.view_image(self.size, self.pos, self.root.canvas, self.img_name, self.img_widget) return def build(self): self.image = None self.img_name = "TestImage.png" self.img_widget = None # 保存ImageKv实例 self.img_h = 2000 self.img_w = 3000 (dim_x, dim_y) = Window.size self.pos = (0, int(dim_y*0.1)) self.size = (int(dim_x * 0.9),int(dim_y*0.7)) x_center = dim_x/2 y_center = dim_y/2 self.polygon = [x_center - dim_x/2, y_center - dim_y/2, x_center - dim_x/2, y_center + dim_y/2, x_center + dim_x/2, y_center + dim_y/2, x_center + dim_x/2, y_center - dim_y/2] root = RelativeLayout(size =(dim_x, dim_y)) slider_hor = Slider(min= 0, max=360, step = 10, value = 0, orientation='horizontal', size_hint = (0.9, 0.1), pos = (0,int(dim_y*4/5.0))) root.add_widget(slider_hor) slider_hor.bind(value=self.OnAzmSliderValueChange) bt_ready = Button(text = 'OK', pos = (0, 0), size_hint = (1,0.1), on_press = self.cmd_ok) root.add_widget(bt_ready) self.root = root return root def cmd_ok(self, instance): self.image = Image.new("RGB", (self.img_w, self.img_h), 'yellow') self.photo = ImageDraw.Draw(self.image) self.photo.polygon(self.polygon, fill = 'red') self.image.save(self.img_name) self.view = View() # 第一次创建保存实例 self.img_widget = self.view.view_image(self.size, self.pos, self.root.canvas, self.img_name) return if __name__ == '__main__': MainApp().run()
内容的提问来源于stack exchange,提问作者jasan
相关产品推荐
相关产品推荐

