tkinter和PIL这两个库在python3.x是内置的,不需要额外安装
最近在学习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,width=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=tk.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()