python - 为什么我的 tkinter 标签上的文件夹中的所有图像都没有显示在画布上的框架内?
问题描述
我正在编写一个 python tkinter 脚本,以从 opencv 创建的文件夹中检索 .jpg 文件,并以水平方式将所有这些文件彼此相邻显示。我可以让代码工作,因为它显示 jpg 文件彼此相邻。然而,在一些帧之后,tkinter 将一个 jpg 文件放在另一个之上,直到最后一个 jpg 文件。不知道我做错了什么。下面是我的脚本。任何建议表示赞赏。
import os
import sys
from Tkinter import *
from PIL import Image, ImageTk
import tkFileDialog
path = 'C:\\JPEGs'
images = []
for dirname, dirnames, filenames in os.walk(path):
for filename in filenames:
file = os.path.join(dirname, filename)
if '.jpg' in file.lower() :
images.append(file)
images.sort(key=lambda f: int(filter(str.isdigit, f)))
#print images
## Main window
root = Tk()
root.geometry('1280x720')
root.title("VIDYOANALYSER-Sachin Chandrashekar")
root.wm_iconbitmap('ad1.ico')
## Grid sizing behavior in window
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
# Canvas
cnv = Canvas(root,bg="light yellow")
cnv.grid(row=0, column=0, sticky='nswe')
## Scrollbars for canvas
hScroll = Scrollbar(root, orient=HORIZONTAL, command=cnv.xview)
hScroll.grid(row=1, column=0, sticky='we')
vScroll = Scrollbar(root, orient=VERTICAL, command=cnv.yview)
vScroll.grid(row=0, column=1, sticky='ns')
cnv.configure(xscrollcommand=hScroll.set, yscrollcommand=vScroll.set)
# Frame in canvas
frm = Frame(root,bg="light yellow")
## This puts the frame in the canvas's scrollable zone
cnv.create_window(0, 0, window=frm, anchor='nw')
## Frame contents
columnCount=0
for files in images:
im = Image.open(files)
tkimage = ImageTk.PhotoImage(im)
myvar=Label(frm,image = tkimage,text=str(os.path.basename(files).strip('.jpg')), compound=TOP,bg='sky blue',relief=SUNKEN)
myvar.image = tkimage
myvar.grid(row=0, column=columnCount, sticky='nswe')
myvar.grid_rowconfigure(0, weight=1)
myvar.grid_columnconfigure(0, weight=1)
columnCount += 1
## Update display to get correct dimensions
frm.update_idletasks()
myvar.update_idletasks()
## Configure size of canvas's scrollable zone
cnv.configure(scrollregion=(0, 0, frm.winfo_width(), frm.winfo_height()))
## Go!
root.mainloop()
预期:有 253 个 jpeg 文件,我希望显示所有帧。检查链接 - https://i.stack.imgur.com/BRMTy.png 实际:仅显示 243 个文件,其余帧显示在另一个上方,只有最后一帧(裁剪一半)在UI.Check 链接 - https://i.stack.imgur.com/KqMeL.png
解决方案
正如@Jasonharper 指出的那样, tkinter 在这种情况下使用 16 位坐标。(不确定这是否对所有容器都相同)。
我已经修改了您的代码以包含一些测量值,以便我们可以看到我们的总图像大小与总标签大小的比较。
我添加了 2 个变量:
total_image_size = 0
total_widget_size = 0
然后在创建所有小部件时,我检查每个图像的大小并更新total_image_size
。
然后我遍历框架中的所有小部件以获取它们的宽度winfo_width()
并更新total_widget_size
。
然而,我们必须运行这个程序两次。第一次查看在开始堆叠图像之前显示了多少图像,第二次在更新计算小部件的循环之后查看小部件的大小,因为我们不想计算小部件的宽度堆叠的小部件。
通过下面的代码,您可以看到 16 位坐标限制是准确的,因为在堆叠之前放置的最后一个小部件将总宽度设置为 32736。如果我们考虑下图中显示的小间隙,我们可以说高限制所在的准确度。
我的测试图像测量为 82 像素宽,小部件测量为每个图像/小部件 88 像素宽。
结论:
根据您的需要,仅加载大量图像列表可能无法在此处工作,但是如果您使用列表来存储图像或图像路径,则可以使用比例滚动它们并将它们动态加载到 from 中以绕过此限制。
结果:
代码:
import os
import tkinter as tk
from PIL import Image, ImageTk
path = r'complete\file\path\here'
images = []
total_image_size = 0
total_widget_size = 0
for dirname, dirnames, filenames in os.walk(path):
for filename in filenames:
file = os.path.join(dirname, filename)
images.append(file)
tk.Tcl().call('lsort', '-dict', images)
root = tk.Tk()
root.geometry('1280x720')
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
cnv = tk.Canvas(root,bg="light yellow")
cnv.grid(row=0, column=0, sticky='nswe')
hScroll = tk.Scrollbar(root, orient='horizontal', command=cnv.xview)
hScroll.grid(row=1, column=0, sticky='we')
vScroll = tk.Scrollbar(root, orient='vertical', command=cnv.yview)
vScroll.grid(row=0, column=1, sticky='ns')
cnv.configure(xscrollcommand=hScroll.set, yscrollcommand=vScroll.set)
frm = tk.Frame(root, bg="light yellow")
cnv.create_window(0, 0, window=frm, anchor='nw')
columnCount = 0
for files in images:
im = Image.open(files)
width, height = im.size
total_image_size += width
tkimage = ImageTk.PhotoImage(im)
myvar = tk.Label(frm, image=tkimage, text=str(os.path.basename(files).strip('.jpg')),
compound='top', bg='sky blue', relief='sunken')
myvar.image = tkimage
myvar.grid(row=0, column=columnCount, sticky='nswe')
myvar.grid_rowconfigure(0, weight=1)
myvar.grid_columnconfigure(0, weight=1)
columnCount += 1
frm.update_idletasks()
cnv.configure(scrollregion=(0, 0, frm.winfo_width(), frm.winfo_height()))
def do_thing():
global total_widget_size
for ndex, widget in enumerate(frm.winfo_children()):
if ndex <= 371: # set the last image to be loaded before stacking started.
total_widget_size += widget.winfo_width()
print('Total widget width prior to stacking', total_widget_size)
print('Total image width', total_image_size)
# short delay so we can check size after all images have been loaded.
# If it takes longer than 3 seconds for your app to load then change this time to be more.
root.after(3000, do_thing)
root.mainloop()
使用的测试图像:
推荐阅读
- javascript - jquery .each 函数在 iframe 中不起作用
- javascript - 从数组中删除特定对象 - Node.js
- c# - 同一解决方案中两个 ASP.NET Core 项目之间的通信
- javascript - 如何修复具有多重嵌套的下拉菜单?香草JS
- javascript - 在句子中找到圆括号并筛选它们
- javascript - 如果其他条件在 Javascript 模板文字中不起作用
- javascript - 在画布上绘图时,触摸事件仅发生一次
- liquibase - How to use one ChangeLog inside another in Liquibase?
- sql - 甲骨文中IN的行为
- mysql - 如何将所有数据库备份与数据库名称相同