• tkinter绘制组件(37)——普通图片


    引言

    其实,本来不打算专门为TinUI写图片元素控件的,让编写者自行使用PhotoImage类和画布自带的create_image方法。但是,因为TinUIXml类的使用,使得界面编写不再需要那么多与ui准备操作相关的逻辑代码,所以有必要(虽然我还是觉得没有太大必要)为TinUI添加image元素,来显示图片。

    提前声明一下,add_image方法的具体目的:

    除了方便、总所周知的Canvas添加图片方法,这里主要讲三种缩放类型。


    布局

    函数结构

        def add_image(self,pos:tuple,width=None,height=None,state='fill',imgfile=None):#绘制静态图片
        '''
        pos-位置
        width-宽度
        height-高度
        state-缩放格式
        imgfile-图片文件
        '''
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    添加图片

    这个就很简单,读者,就默认你已经熟悉了tkinter图片显示功能。

    在三种缩放,none模式无疑是最简单的,就是从左上角裁剪。

            state=state.lower()
            if state=='none' and (width!=None or height!=None):#直接左上角裁剪
                image=PhotoImage(file=imgfile,width=width,height=height)
                width,height=None,None
            else:
                image=PhotoImage(file=imgfile)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    现在,直接显示图片,方便我们获取图片原本的尺寸:

            self.images.append(image)#存储图片,防止被python垃圾回收
            img=self.create_image(pos,anchor='nw',image=self.images[-1])
            bbox=self.bbox(img)
            rwidth,rheight=bbox[2]-bbox[0],bbox[3]-bbox[1]
    
    • 1
    • 2
    • 3
    • 4

    因为python传奇的垃圾回收机制,类中对PhotoImage的实例无法保存,需要使用一些固定的载体,比如BasicTinUI的属性之一:images:list

    图片缩放

    我也是借鉴(新学)的,tkinter自身可以实现图片任意比例缩放,不过可能比PIL慢些。

    具体步骤:

    1. 通过zoom方法设定缩放最小基数(精确度)

    2. 通过subsample方法按比例缩放图片

    翻译成代码就如下:

            if width!=None or height!=None:#缩放
                #缩放系数
                xrate=width/rwidth if width!=None else 1
                yrate=height/rheight if height!=None else 1
                if state=='uniform':#等比缩放
                    #取最小值
                    if yrate<xrate:
                        xrate=yrate
                    else:#yrate>=xrate
                        yrate=xrate
                #else:state=='fill'
                key=round(2)
                image=PhotoImage.zoom(image,key,key)
                image=image.subsample(round(key/xrate),round(key/yrate))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    当然咯,因为img元素不可能跟着改变,所以要重新为其指定图片信息,别忘了更改图片列表最后一个元素。

                #...
                self.images[-1]=image
                self.itemconfig(img,image=self.images[-1])
    
    • 1
    • 2
    • 3

    完整函数代码

        def add_image(self,pos:tuple,width=None,height=None,state='fill',imgfile=None):#绘制静态图片
            #这个控件是静态gif或者是png图片
            #state::none裁剪操作,fill填充,uniform等比缩放
            state=state.lower()
            if state=='none' and (width!=None or height!=None):#直接左上角裁剪
                image=PhotoImage(file=imgfile,width=width,height=height)
                width,height=None,None
            else:
                image=PhotoImage(file=imgfile)
            self.images.append(image)#存储图片,防止被python垃圾回收
            img=self.create_image(pos,anchor='nw',image=self.images[-1])
            bbox=self.bbox(img)
            rwidth,rheight=bbox[2]-bbox[0],bbox[3]-bbox[1]
            if width!=None or height!=None:#缩放
                #缩放系数
                xrate=width/rwidth if width!=None else 1
                yrate=height/rheight if height!=None else 1
                if state=='uniform':#等比缩放
                    #取最小值
                    if yrate<xrate:
                        xrate=yrate
                    else:#yrate>=xrate
                        yrate=xrate
                #else:state=='fill'
                key=round(2)
                image=PhotoImage.zoom(image,key,key)
                image=image.subsample(round(key/xrate),round(key/yrate))
                self.images[-1]=image
                self.itemconfig(img,image=self.images[-1])
            return img
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    效果

    测试代码

    # 见 test\image.py
    
    • 1

    最终效果

    在这里插入图片描述

    2023-1-16更新

    将图片缩放的精度调成十位小数点。


    github项目

    TinUI的github项目地址

    pip下载

    pip install tinui
    
    • 1

    结语

    image在tkinter其实并不是一个单独控件,而是一个参数,不过TinUI把它拎了出来,也就凑合着用吧。以后可能会接受PIL提供的ImageTk。TinUI4.0开始还会随包发布帮助手册应用。

    🔆tkinter创新🔆

  • 相关阅读:
    3.Netty中Channel通道概述
    Quick MTF 照相机镜头图像质量测试程序-UPDATE
    征集 |《新程序员》专访Python之父,你最想问什么?
    Redis-使用java代码操作Redis
    OneFlow技术年货:800+页免费“大模型”电子书
    Python 框架学习 Django篇 (十) Redis 缓存
    Go学习之路:并发(DAY 3)
    继GitHub的Copilot收费后,亚马逊推出了 CodeWhisperer,感觉不错哟!
    LeetCode 刷题 [C++] 第236题.二叉树的最近公共祖先
    2023-2024-1 for循环-1
  • 原文地址:https://blog.csdn.net/tinga_kilin/article/details/128066452