IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> Python + Tkinter:简易图片浏览器 -> 正文阅读

[Python知识库]Python + Tkinter:简易图片浏览器

作者:>

??????? 系统默认的图片显示软件用着不顺手,心血来潮自己捣鼓一个简单易用的图片浏览器。另外不会留下垃圾和痕迹不是?!???????

????????直接代码:

"""
@author: MR.N
@created: 2021-08-07 Sat. 14:02

"""

import tkinter as tk
import os
# 文件读写IO
from fio import *
from PIL import Image, ImageTk
# 库的导入管理
from pio import *


# 初始化窗口宽度
S_WIDTH = 876
# 初始化窗口高度
S_HEIGHT = 700
# 初始化图片最大宽度
I_WIDTH = 710
# 初始化图片最大高度
I_HEIGHT = 670


# 获取当前文件夹的所有图片信息
def get_caches():
    current_dir = os.getcwd()
    cache_dir = current_dir + '/' + IMAGE_CACHE_DIR + '/'
    caches = os.listdir(cache_dir)
    temp_caches = []
    for cache in caches:
        temp_caches.append(cache_dir + cache)
    caches.sort(key=lambda fn: os.path.getmtime(cache_dir+fn), reverse=True)
    temp_caches.sort(key=lambda fn: os.path.getmtime(fn), reverse=True)
    return caches, temp_caches


# 按比例缩放图片
def resize(path, scale=-1):
    image = Image.open(path)
    # 按照当前窗口的大小最大缩放图片
    if scale == -1:
        raw_width, raw_height = image.size[0], image.size[1]
        max_width, max_height = I_WIDTH, I_HEIGHT
        min_height = min(max_height, raw_height)
        min_width = int(raw_width * min_height / raw_height)
        if min_width > max_width:
            min_width = min(max_width, raw_width)
            min_height = int(raw_height * min_width / raw_width)
    # 缩略图缩放
    elif scale == 1:
        raw_width, raw_height = image.size[0], image.size[1]
        min_height = 166
        min_width = int(raw_width * min_height / raw_height)
    # 工具栏图标icon缩放
    else:
        raw_width, raw_height = image.size[0], image.size[1]
        min_height = 20
        min_width = int(raw_width * min_height / raw_height)
    return image.resize((min_width, min_height))


class MyGallery:
    def __init__(self):
        self.window = tk.Tk()
        self.window.title('ImageCape')
        self.window.wm_title('ImageCape')
        self.window.geometry(str(S_WIDTH)+'x'+str(S_HEIGHT)+'+50+200')
        self.frame = tk.Frame(self.window)
        # self.frame2 = tk.Frame(self.window)
        self.frame3 = tk.Frame(self.window)
        self.window.config(bg='#111')
        self.window.rowconfigure(0, weight=1)
        self.window.rowconfigure(1, weight=1)
        # self.window.rowconfigure(2, weight=1)
        self.window.columnconfigure(0, weight=1)
        self.window.columnconfigure(1, weight=1)
        # self.window.columnconfigure(2, weight=1)
        self.frame.columnconfigure(0, weight=1)
        self.frame3.rowconfigure(0, weight=1)
        self.frame3.columnconfigure(0, weight=1)
        self.frame3.config(bg='#111')

        self.remote_url = tk.StringVar()
        self.text = tk.Entry(self.frame, width=S_WIDTH, textvariable=self.remote_url)
        self.text.config(bg='#eee')
        self.text.config(fg='#111')
        self.text.config(highlightcolor='#999')
        self.text.grid(row=0, sticky=tk.E)
        self.text.bind('<Button-1>', self.reset_tip_bar)
        self.text.bind('<Return>', self.load_image_remote)
        # 下载图片按钮,略
        self.enter_button = tk.Button(self.frame, text='Cap it!', width=20, height=20)
        go_icon = ImageTk.PhotoImage(resize(os.getcwd() + '/go.jpeg', 0))
        self.enter_button.config(image=go_icon)
        self.enter_button.bind('<Button-1>', self.load_image_remote)
        self.enter_button.grid(row=0, column=1, sticky=tk.E)
        # 删除按钮
        self.del_button = tk.Button(self.frame, text='DEL', width=20, height=20)
        # Bug occurs in the following code.
        # self.del_button.config(image=ImageTk.PhotoImage(resize(os.getcwd() + '/delete.png', 0)))
        del_icon = ImageTk.PhotoImage(resize(os.getcwd() + '/delete.png', 0))
        self.del_button.config(image=del_icon)
        self.del_button.bind('<Button-1>', self.delete_selected_image)
        self.del_button.grid(row=0, column=2, sticky=tk.W)
        # 地址栏和工具栏的布局
        self.frame.grid(row=0, sticky=tk.N+tk.W+tk.E)
        self.frame.rowconfigure(0, weight=1)
        self.frame.columnconfigure(0, weight=1)

        # self.frame2.grid(row=2, column=0, sticky=tk.W+tk.E)
        # self.frame2.rowconfigure(0, weight=1)
        # self.frame2.columnconfigure(1, weight=1)
        # self.frame2.columnconfigure(0, weight=1)

        self.caches, self.cache_paths = get_caches()
        self.image_pos = 0
        if len(self.caches) > 0 and len(self.caches) > self.image_pos >= 0:
            image = resize(self.cache_paths[self.image_pos])
            photo = ImageTk.PhotoImage(image)
        else:
            photo = None
        # 显示当前图片
        self.label = tk.Label(self.frame3, text=self.caches[self.image_pos],
                              padx=1, pady=1, image=photo)
        self.label.config(bg='#111')
        self.label.config(justify='center')
        self.label.focus_get()
        # 点击鼠标左键,显示下一张图片的大图
        self.label.bind('<Button-1>', self.set_next_image)
        # 点击鼠标右键,则显示上一张大图
        self.label.bind('<Button-3>', self.set_prev_image)
        self.label.grid(row=0, column=0, rowspan=4, sticky=tk.NSEW)
        # 缩略图列表
        self.sub_label = tk.Label(self.frame3, text='Empty', width=166, height=166,
                                  padx=1, pady=1)
        self.sub_label.config(bg='#111')
        self.sub_image = None
        self.sub_photo = None
        # 绑定第1张缩略图的鼠标左键点击事件为self.load_sub_image_1——显示缩略图的大图
        self.sub_label.bind('<Button-1>', self.load_sub_image_1)
        self.sub_label.grid(row=0, column=1, sticky=tk.NE)

        self.sub_label2 = tk.Label(self.frame3, text='Empty', width=166, height=166, padx=1, pady=1)
        self.sub_label2.config(bg='#111')
        self.sub_image2 = None
        self.sub_photo2 = None
        # 绑定第2张缩略图的鼠标左键点击事件为self.load_sub_image_2——显示缩略图的大图
        self.sub_label2.bind('<Button-1>', self.load_sub_image_2)
        self.sub_label2.grid(row=1, column=1, sticky=tk.NE)

        self.sub_label3 = tk.Label(self.frame3, text='Empty', width=166, height=166, padx=1, pady=1)
        self.sub_label3.config(bg='#111')
        self.sub_image3 = None
        self.sub_photo3 = None
        # 绑定第3张缩略图的鼠标左键点击事件为self.load_sub_image_3——显示缩略图的大图
        self.sub_label3.bind('<Button-1>', self.load_sub_image_3)
        self.sub_label3.grid(row=2, column=1, sticky=tk.NE)

        self.sub_label4 = tk.Label(self.frame3, text='Empty', width=166, height=166, padx=1, pady=1)
        self.sub_label4.config(bg='#111')
        self.sub_image4 = None
        self.sub_photo4 = None
        # 绑定第4张缩略图的鼠标左键点击事件为self.load_sub_image_4——显示缩略图的大图
        self.sub_label4.bind('<Button-1>', self.load_sub_image_4)
        self.sub_label4.grid(row=3, column=1, sticky=tk.NE)

        self.reset_sub_image()
        # 大图和缩略图列表的UI界面布局
        self.frame3.grid(row=1, column=0, sticky=tk.N+tk.W+tk.E)
        self.frame3.columnconfigure(0, weight=1)
        self.frame3.rowconfigure(0, weight=1)
        # 上一张图片按钮
        self.prev_button = tk.Button(self.frame, width=20, height=20, text='Prev')
        prev_icon = ImageTk.PhotoImage(resize(os.getcwd() + '/backward.png', 0))
        self.prev_button.config(image=prev_icon)
        self.prev_button.config(bd=1)
        # 绑定上一张按钮的鼠标左键点击事件
        self.prev_button.bind('<Button-1>', self.set_prev_image)
        self.prev_button.grid(row=0, column=3, padx=0, sticky=tk.E)
        # 下一张图片按钮
        self.next_button = tk.Button(self.frame, width=20, height=20, text='Next')
        next_icon = ImageTk.PhotoImage(resize(os.getcwd() + '/forward.png', 0))
        self.next_button.config(image=next_icon)
        # 绑定下一张按钮的鼠标左键点击事件
        self.next_button.bind('<Button-1>', self.set_next_image)
        self.next_button.grid(row=0, column=4, padx=0, sticky=tk.E)

        self.window.mainloop()

    def __del__(self):
        self.window = None

    def reset_tip_bar(self, event):
        self.text.config(highlightcolor='#999')

    def reload_caches(self):
        self.caches, self.cache_paths = get_caches()

    # 重置缩略图列表
    def reset_sub_image(self):
        # sub image 1
        if len(self.caches) > 0 and len(self.caches) > self.image_pos+1 > 0:
            self.sub_image = resize(self.cache_paths[self.image_pos+1], 1)
            self.sub_photo = ImageTk.PhotoImage(self.sub_image)
        elif len(self.caches) > 0 and len(self.caches) == self.image_pos+1:
            self.sub_image = resize(self.cache_paths[len(self.caches)-1], 1)
            self.sub_photo = ImageTk.PhotoImage(self.sub_image)
        else:
            self.sub_photo = None
        self.sub_label.config(image=self.sub_photo)
        # sub image 2
        if len(self.caches) > 0 and len(self.caches) > self.image_pos+2 > 0:
            self.sub_image2 = resize(self.cache_paths[self.image_pos+2], 1)
            self.sub_photo2 = ImageTk.PhotoImage(self.sub_image2)
        else:
            self.sub_photo2 = None
        self.sub_label2.config(image=self.sub_photo2)
        # sub image 3
        if len(self.caches) > 0 and len(self.caches) > self.image_pos+3 > 0:
            self.sub_image3 = resize(self.cache_paths[self.image_pos+3], 1)
            self.sub_photo3 = ImageTk.PhotoImage(self.sub_image3)
        else:
            self.sub_photo3 = None
        self.sub_label3.config(image=self.sub_photo3)
        # sub image 4
        if len(self.caches) > 0 and len(self.caches) > self.image_pos+4 > 0:
            self.sub_image4 = resize(self.cache_paths[self.image_pos+4], 1)
            self.sub_photo4 = ImageTk.PhotoImage(self.sub_image4)
        else:
            self.sub_photo4 = None
        self.sub_label4.config(image=self.sub_photo4)

    # 加载第1张缩略图
    def load_sub_image_1(self, event):
        if len(self.caches) > 0 and len(self.caches) > self.image_pos+1 > 0:
            self.image_pos += 1
            self.load_image(self.image_pos)
        self.reset_sub_image()

    # 加载第2张缩略图
    def load_sub_image_2(self, event):
        if len(self.caches) > 0 and len(self.caches) > self.image_pos+2 > 0:
            self.image_pos += 2
            self.load_image(self.image_pos)
        self.reset_sub_image()

    # 加载第3张缩略图
    def load_sub_image_3(self, event):
        if len(self.caches) > 0 and len(self.caches) > self.image_pos+3 > 0:
            self.image_pos += 3
            self.load_image(self.image_pos)
        self.reset_sub_image()

    # 加载第4张缩略图
    def load_sub_image_4(self, event):
        if len(self.caches) > 0 and len(self.caches) > self.image_pos+4 > 0:
            self.image_pos += 4
            self.load_image(self.image_pos)
        self.reset_sub_image()

    # 图片下载器ImgLoader,此处略
    def load_image_remote(self, event):
        url = self.remote_url.get()
        self.text.delete(0, tk.END)
        # 简单验证URL地址是否有效
        if not verify_path_loose(url):
            return
        print('[process]', 'forked')
        start_time = time.time()
        time.sleep(.1)
        # 下载图片流程略
        ...
        end_time = time.time()
        print('[process]', 'done with', '%.3f' % (end_time - start_time) + ' s.')

    # 删除当前显示的图片
    def delete_selected_image(self, event=None):
        if len(self.caches) > 0 and len(self.caches) > self.image_pos >= 0:
            try:
                os.remove(self.cache_paths[self.image_pos])
                self.text.config(highlightcolor='yellow')
                self.reload_caches()
                self.set_prev_image()
            except FileNotFoundError:
                self.text.config(highlightcolor='red')

    # 显示当前定位的图片
    def load_image(self, position=0):
        if len(self.caches) > 0 and len(self.caches) > position >= 0:
            try:
                image = resize(self.cache_paths[position])
                photo = ImageTk.PhotoImage(image)
                self.label.config(image=photo)
                self.label.image = photo
                # print(self.caches[position])
            except FileNotFoundError:
                self.reload_caches()
        else:
            photo = None
            self.label.config(image=photo)
            self.label.image = photo

    # 上一张图片
    def set_prev_image(self, event=None):
        if len(self.caches) > 0 and len(self.caches) > self.image_pos > 0:
            self.image_pos -= 1
        else:
            self.reload_caches()
            self.image_pos = 0
        self.load_image(self.image_pos)
        # 更新缩略图列表
        self.reset_sub_image()

    # 下一张图片
    def set_next_image(self, event=None):
        if len(self.caches) > 0 and len(self.caches)-1 > self.image_pos >= 0:
            self.image_pos += 1
        else:
            self.reload_caches()
            self.image_pos = len(self.caches) - 1
        self.load_image(self.image_pos)
        # 更新缩略图列表
        self.reset_sub_image()


my_gallery = MyGallery()

????????界面图:

?

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-08-14 13:59:04  更:2021-08-14 14:00:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/26 12:21:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计