KivyMD中如何设置导入图片的位置并保持其原始朝向?
修复方案
前置依赖
先安装图片处理库Pillow:
pip install pillow
核心修改点
- 新增EXIF朝向处理逻辑:读取图片的EXIF元数据,自动将图片旋转到正确朝向
- 调整Image组件配置:开启比例保持,避免图片拉伸变形,同时通过
pos_hint自定义图片位置 - 图片加载逻辑修改:将处理后的图片转为Kivy纹理直接赋值,避免临时文件读写
完整可运行代码
from kivy.lang import Builder from kivymd.app import MDApp from kivy.core.window import Window from kivy.graphics.texture import Texture from plyer import filechooser from PIL import Image as PILImage, ExifTags import io Window.size = (300, 530) KV = """ MDBoxLayout: orientation: 'vertical' MDToolbar: id: progress_toolbar title: 'Progress' ScrollView: MDGridLayout: cols: 2 adaptive_height: True spacing: (10, 15) padding: [25, 25] MDLabel: halign: 'center' text: 'Before' MDLabel: halign: 'center' text: 'Now' MDCard: ripple_behavior: True orientation: 'vertical' size_hint_y: None size: 120, 220 elevation: 15 radius: 8 MDIconButton: icon: "camera-outline" user_font_size: "24sp" pos_hint: {"center_x": .5, "center_y": .5} on_release: app.file_chooser1() Image: id: img1 allow_stretch: True keep_ratio: True size_hint: 0.9, 0.9 # 调整以下参数自定义图片位置 pos_hint: {"center_x": 0.5, "center_y": 0.4} MDCard: ripple_behavior: True orientation: 'vertical' size_hint_y: None size: 120, 220 elevation: 15 radius: 8 MDIconButton: icon: "camera-outline" user_font_size: "24sp" pos_hint: {"center_x": .5, "center_y": .5} on_release: app.file_chooser2() Image: id: img2 allow_stretch: True keep_ratio: True size_hint: 0.9, 0.9 # 调整以下参数自定义图片位置 pos_hint: {"center_x": 0.5, "center_y": 0.4} MDTextField: hint_text: 'Date' width: 100 MDTextField: hint_text: 'Date' width: 100 """ class Example(MDApp): def build(self): return Builder.load_string(KV) # 辅助函数:处理图片EXIF朝向 def fix_image_orientation(self, img): try: for orientation in ExifTags.TAGS.keys(): if ExifTags.TAGS[orientation]=='Orientation': break exif = img._getexif() if exif is not None: orientation = exif[orientation] if orientation == 3: img = img.rotate(180, expand=True) elif orientation == 6: img = img.rotate(270, expand=True) elif orientation == 8: img = img.rotate(90, expand=True) except (AttributeError, KeyError, IndexError): # 图片没有EXIF信息的情况直接返回原图 pass return img # 辅助函数:将PIL图片转为Kivy纹理 def pil_to_texture(self, pil_img): pil_img = pil_img.convert('RGBA') data = pil_img.tobytes() texture = Texture.create(size=pil_img.size, colorfmt='rgba') texture.blit_buffer(data, colorfmt='rgba', bufferfmt='ubyte') texture.flip_vertical() return texture def file_chooser1(self): filechooser.open_file(on_selection=self.selected1) def file_chooser2(self): filechooser.open_file(on_selection=self.selected2) def selected1(self, selection1): if not selection1: return # 读取并处理图片 pil_img = PILImage.open(selection1[0]) pil_img = self.fix_image_orientation(pil_img) self.root.ids.img1.texture = self.pil_to_texture(pil_img) def selected2(self, selection2): if not selection2: return # 读取并处理图片 pil_img = PILImage.open(selection2[0]) pil_img = self.fix_image_orientation(pil_img) self.root.ids.img2.texture = self.pil_to_texture(pil_img) Example().run()
自定义位置说明
你可以直接修改每个Image组件的pos_hint参数调整位置:
center_x取值范围0~1,0为最左侧,1为最右侧,0.5为水平居中center_y取值范围0~1,0为最底部,1为最顶部,0.5为垂直居中
如果需要固定偏移量,也可以直接设置x和y属性指定绝对坐标。
内容的提问来源于stack exchange,提问作者Edwin
相关产品推荐
相关产品推荐

