最近在学习python,就用python自己写了一个仿windows的看图器,在网上搜发现找不到相关的代码,所以决定自己尝试做了一个。看图器要实现如下功能:

  • 打开文件夹,找到相应文件
  • 图片可以进行等比例缩放
  • 可以浏览同目录问价下的上一张和下一张图片

1.用label方法制作看图器

由于python的tkinter库只能打开gif文件不能打开jpg等其它文件,所以这里需要导入PIL库。tkinter的学习建议参考莫烦的视频。莫烦tkinter教程。讲解非常详细配有简单案例适合初学者学习。

import tkinter as tk
from PIL import ImageTK,Image
from tkinter import filedialog       #获取文件全路径

root=tk.Tk()   #创建对象
root.title('图片查看器')     #窗口的名称
root.geometry('400x400')     #规定窗口大小

l=tk.Label(root,text='pictures will show in this place', image=None)   #创建一个标签
l.pack()     #放置标签

def openpicture():
    global img
    filename=filedialog.askopenfilename()     #获取文件全路径
    img=ImageTk.PhotoImage(Image.open(filename))   #tkinter只能打开gif文件,这里用PIL库
    # 打开jpg格式的文件
    l.config(image=img)    #用config方法将图片放置在标签中
 
b=kt.Button(root,text='select a picture', command=openpicture)  #设置按钮,并给它openpicture命令
b.pack()

tk.mainloop()

我们开看一下运行效果:


点击选择按钮:


选择一张图片:



这样一个简单的查看器就做完了,但是可以看到当图片的像素太大的时候图片无法显示完全,所以需要对程序进行修改让它能够按标签的大小进行缩放。但是经过我多次测试,geometry大小设置的是400x400,label标签大小设置的是300x300,但遗憾的是最后标签填满了整个窗口,猜测的原因可能是geometry和label的单位不同造成的,于是我改变了label的大小,设置为30x300,但最终标签仍然充满了整个窗口,查阅资料没能解决是什么原因导致这一问题

2.用canvas方法制作看图器

在label方法遇到困难后转向了canvas方法,直接绘制画布大小。由于每张图片的尺寸不一样,要想将图片保持原来的长宽比显示在canvas上需要将图像进行缩放。

import tkinter as tk
from PIL import ImageTK,Image
from tkinter import filedialog       #获取文件全路径

root=tk.Tk()  
root.title('图片查看器')     
root.geometry('500x500')     

canvas=tk.Canvas(root,height=400,height=400)   #画布长款定为400x400
canvas.pack()

def openpicture():
    global img
    filename=filedialog.askopenfilename()     #获取文件全路径
    image=Image.open(filename)        #打开图片放到image中
    w,h=image.size     #获取image的长和宽
    mlength=max(w,h)    #取最大的一边作为缩放的基准
    mul=400/mlength    #缩放倍数
    w1=int(w*mul)
    h1=int(h*mul)
    re_image=image.resize((w1,h1))
    img=ImageTK.PhotoImage(re_image)    #在canvas中展示图片
    canvas.create_image(200,200,anchor='center',image=img)   #以中小点为锚点
 
b=kt.Button(root,text='select a picture', command=openpicture)  #设置按钮,并给它openpicture命令
b.pack()

tk.mainloop()


浏览上一张和下一张

这里我的思想是:

  • 先获取该文件的完整路径
  • 获取该文件的上一级路径
  • 获取该文件的文件名
  • 通过os.listdir()获取该文件夹下的所有文件并生成列表
  • 通过列表找到该文件的索引值
  • 将索引值+1,-1实现上一张,下一张的功能
    思想很简单,在这里我将之前得分代码重新整理,把不同功能进行了封装
import tkinter as tk
from PIL import ImageTk,Image
from tkinter import filedialog
import os

root=tk.Tk()
root.title('图片查看器')
root.geometry('500x500')

canvas=tk.Canvas(root,height=400,width=400)
canvas.pack()

path=tk.StringVar()

def resize(image):
    w, h = image.size
    mlength = max(w, h)  # 找出最大的边
    mul = 400 / mlength  # 缩放倍数
    w1 = int(w * mul)  # 重新获得高和宽
    h1 = int(h * mul)
    return image.resize((w1, h1))

def show_image(path):
    global img   #要申明全局变量我猜测是调用了canvas
    image = Image.open(path)  # 打开图片
    re_image = resize(image)  # 调用函数
    img = ImageTk.PhotoImage(re_image)  # PhotoImage类是用来在label和canvas展示图片用的
    canvas.create_image(200, 200, anchor='center', image=img)

def openpicture():
#打开一张图片并显示
    global fileindex,fatherpath,files,file_num

    filepath=filedialog.askopenfilename()
    fatherpath=os.path.dirname(filepath)      #获取该路径的上一级路径
    filename=os.path.basename(filepath)   #获取该路径下的文件名
    files=os.listdir(fatherpath)     #该路径下的所有文件并生成列表
    file_num=len(files)
    fileindex=files.index(filename)    #获取当前文件的索引值
    show_image(filepath)


def previous():
    global fileindex, fatherpath, files,file_num
    fileindex -=1
    if fileindex == -1:
        fileindex = file_num-1
    filepath1=os.path.join(fatherpath, files[fileindex])
    show_image(filepath1)

def back():
    global fileindex, fatherpath, files,file_num
    fileindex += 1
    if fileindex == file_num:
        fileindex = 0
    filepath2 = os.path.join(fatherpath, files[fileindex])
    show_image(filepath2)

b=tk.Button(root,text='select a picture',command=openpicture)
b.pack()

b1=tk.Button(root,text='上一张',command=previous).pack(side='left')
b2=tk.Button(root,text='下一张',command=back).pack(side='right')

tk.mainloop()