tkinter实现图片交换位置和图片浏览排列

效果

效果如下:

用鼠标拖动,交换第一张图片和第二张图片的位置。

 

 代码

import fnmatch
import os
from tkinter import *
import numpy as np

from PIL import ImageTk
from PIL import Image as imim  # 要用别名


def changeOrder(widget1, widget2, initial):
    """
    实现组件位置互换的操作
    :param widget1:首次鼠标点击拖拽的标签对象
    :param widget2:拖拽中根据鼠标位置  获得的标签对象
    :param initial:首次鼠标点击拖拽的初始位置  grid布局
    """
    target = widget1.grid_info()
    # 拖拽过程中,鼠标的位置未进入另一个组件里面 会报错
    try:
        widget1.grid(row=initial['row'], column=initial['column'])
        widget2.grid(row=target['row'], column=target['column'])
    except KeyError:
        pass


def on_click(event):
    """
    用于判断是否点击,释放鼠标按钮
    :param event: 点击事件
    """
    widget = event.widget
    # 判断发生事件的是否是组件
    if isinstance(widget, Label):
        # 鼠标点击事件的初始位置,不是组件的位置
        start = (event.x, event.y)
        # 发生事件的组件的位置
        grid_info = widget.grid_info()
        # 移动图片
        widget.bind("<B1-Motion>", lambda event: drag_motion(event, widget, start))
        # 放置图片
        widget.bind("<ButtonRelease-1>", lambda event: drag_release(event, widget, grid_info))
    else:
        root.unbind("<ButtonRelease-1>")


def drag_motion(event, widget, start):
    """
    用于拖拽label标签
    :param event: 鼠标点击事件
    :param widget: 发生事件的label
    :param start: 发生事件的label的初始位置
    """
    # 获取组件当前位置(随鼠标移动而改变,x,y基于组件左上角边角位置决定)
    x = widget.winfo_x() + event.x - start[0]
    y = widget.winfo_y() + event.y - start[1]
    # label组件置顶
    widget.lift()
    # 根据place实现拖拽移动label
    widget.place(x=x, y=y)


def drag_release(event, widget, grid_info):
    """
    :param event: 鼠标释放事件
    :param widget: 发生事件的label标签
    :param grid_info: label标签原来的位置
    """
    # 组件释放后置于底层
    widget.lower()
    # UI界面相对于电脑屏幕的x,y位置
    x, y = root.winfo_pointerxy()
    # 根据相对位置,确定target是哪个组件对象
    target_widget = root.winfo_containing(x, y)
    # 如果target是组件对象,则换位置
    if isinstance(target_widget, Label):
        changeOrder(target_widget, widget, grid_info)
    # 否则点击事件的组件回归到原来位置
    else:
        widget.grid(row=grid_info['row'], column=grid_info['column'])


root = Tk()
root.geometry("1920x1080")
# 图片文件路径
filepath = "/Users/resource"
# -------------遍历文件获取图片的文件路径
# 符合images的文件路径列表
matches = []
images = ['*.jpg', '*.png','*.jpeg']
n = []
# 平方列表
power = []
x = 0
y = 0
x_list = []
y_list = []
# 计算平方值 根据图片数量分割
for i in range(1, 1000):
    power.append(i * i)
for dirpath, dirnames, filenames in os.walk(os.path.expanduser(filepath)):  # 遍历返回三元组
    for image in images:
        for filename in fnmatch.filter(filenames, image):
            matches.append(os.path.join(dirpath, filename))  # 放入符合文件后缀的路径
# 获取 i,也就是分多少份
for i in range(len(power)):
    if power[i] >= len(matches):
        power.append(i + 1)
        break
# 自动适应大小,根据UI界面分割i份
height = np.around((root.winfo_vrootheight()-96) / power[-1], decimals=0)
width = np.around((root.winfo_vrootwidth()-54) / power[-1], decimals=0)
height = int(height)
width = int(width)
# 自动排列图片
for i in range(1, power[-1] + 1):
    for j in range(1, power[-1] + 1):
        if i == 1:
            x_list.append(x)
            width = width
            x = width + x
    y_list.append(y)
    height = height
    y = height + y
# 根据图片数量,定义多个对象
for i in range(len(matches)):
    n.append("myLabel" + f"{i}")
# 列数 比如9张图分3份 也就是0 1 2
c = 0
# 行数 比如9张图分3份 也就是0 1 2
r = 0
for i in range(len(matches)):
    # 求列数
    column = int((c+3)/3)-1
    # 求行数
    row = int((r+3)/3)-1
    # 打开图片
    image = imim.open(matches[i])
    # 自动适应修改图片大小
    image = image.resize((width, height))
    # 把label标签设置成图片(label参数)
    img_png = ImageTk.PhotoImage(image)
    # 创建label组件
    n[i] = Label(root, image=img_png, text=f"Label {i}", borderwidth=2, relief="raise")
    # 之前CSDN已经发过相关问题的解决, label标签设置成图片变白,无法显示图片
    # 这句必须要加上,否则图片无法显示
    n[i].image = img_png
    # 使用grid布局,做这个东西使用了另一种方法bug太多,所以grid布局好做一点
    n[i].grid(row=row, column=column, padx=2, pady=2, sticky=E + W + S + N)
    # 求行数
    if (i+1) % 3 == 0:
        r = r + 3
        if r == len(matches):
            r = 0
    # 求列数
    else:
        c = c + 3
        if c == len(matches):
            c = 0
# 点击事件绑定
root.bind("<Button-1>", on_click)

root.mainloop()

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

立秋6789

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值