用python的tkinter库制作仿windows看图器

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,但最终标签仍然充满了整个窗口,查阅资料没能解决是什么原因导致这一问题

将标签背景设置成为黄色,窗口400x400,标签height=30,weight=300,但标签填满了整个窗口

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()
图片查看器
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容