tkinter+图片等比例+根据窗口大小缩放

分享一个简单的图片浏览器,一个等比例缩放的算法
使用root.bind方法动态获取窗口大小,不需要重写窗口算法与重新加载图片了,省下了一大笔时间

from PIL import Image, ImageTk
from ttkbootstrap import *


def image_resize(event=None, image=None):
    """
    等比例缩放图片
    :param event: bind事件
    :param image: Image.open(file_path) or Image.open(io.BytesIO(requests.get(url='https://pic2.zhimg.com/v2-2383d0d9ef77715b3cdd61b405dc8aec_1440w.jpg?source=172ae18b').content))
    :return:
    """
    if event is None:
        screen_width, screen_height = win_size()
    else:
        screen_width, screen_height = event.width, event.height
    raw_width, raw_height = image.size[0], image.size[1]
    max_width, max_height = raw_width, screen_height
    min_width = max(raw_width, max_width)
    # 按照比例缩放
    min_height = int(raw_height * min_width / raw_width)
    # 第1次快速调整
    while min_height > screen_height:
        min_height = int(min_height * .9533)
    # 第2次精确微调
    while min_height < screen_height:
        min_height += 1
    # 按照比例缩放
    min_width = int(raw_width * min_height / raw_height)
    # 适应性调整
    while min_width > screen_width:
        min_width -= 1
    # 按照比例缩放
    min_height = int(raw_height * min_width / raw_width)
    images = image.resize((min_width, min_height), Image.Resampling.LANCZOS)
    if event is None:
        return images
    else:
        global png
        canvas.delete(image1)
        png = ImageTk.PhotoImage(images)
        canvas.create_image(screen_width // 2, screen_height // 2, image=png)


def win_size():
	"""
	获取窗口大小,在没有bind事件时使用
	"""
    root.update()
    width = root.winfo_width()
    height = root.winfo_height()
    return width, height


def handler_adaptor(fun, **kwds):
    """事件处理函数的适配器,相当于中介,那个event是从那里来的呢,我也纳闷,这也许就是python的伟大之处吧"""
    return lambda event, fun=fun, kwds=kwds: fun(event, **kwds)


root = Window(size=(1000, 800))
canvas = Canvas(root, bg='#312b39', highlightthickness=0)
canvas.pack(side=LEFT, anchor=CENTER, fill=BOTH, expand=YES)

png = Image.open('1.png')
image = ImageTk.PhotoImage(image=image_resize(image=png, event=None))
image1 = canvas.create_image(win_size()[0] // 2, win_size()[1] // 2, image=image)
root.bind(sequence='<Configure>', func=handler_adaptor(image_resize, image=png))
root.mainloop()

### Tkinter 窗口缩放时布局错位解决方案 当Tkinter窗口被调整大小时,如果组件未正确配置,则可能出现布局错位的情况。为了防止此类问题发生,在设计界面时应合理选用几何管理器并设置相应的参数。 对于`pack()`方法而言,通过指定`fill`和`expand`选项可以控制子部件如何响应父容器尺寸变化[^1]: - `fill`: 定义小部件是否以及怎样填充分配给它的空间;可选值有NONE, X (水平), Y (垂直) 和 BOTH(两个方向)[^1] - `expand`: 当其所在区域超出最小请求宽度/高度时,指示该小部件是否应该扩展以占用额外的空间[^1] 采用`grid()`作为布局方式同样重要的是理解列权重(`columnconfigure`)与行权重(`rowconfigure`)的概念。这允许某些行列比其他部分更灵活地增长或收缩,从而保持良好的视觉比例关系[^2]: ```python import tkinter as tk root = tk.Tk() frame = tk.Frame(root) # 设置第0行和第0列为具有弹性伸展特性 frame.grid_rowconfigure(0, weight=1) frame.grid_columnconfigure(0, weight=1) label = tk.Label(frame, text="这是一个标签") button = tk.Button(frame, text="点击这里") # 将控件放置到网格中,并使它们能够随框架一起拉伸 label.grid(row=0, column=0, sticky='nsew') button.grid(row=1, column=0, sticky='ew') frame.pack(fill=tk.BOTH, expand=True) root.mainloop() ``` 此外,还可以考虑使用`place()`来精确设定每个组件的位置及大小百分比,但这通常适用于较为简单的场景,因为维护绝对定位可能会增加复杂度[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值