Python Tkinter和x27的意外行为;s网格嵌入在包含280多个元素的画布中

Python Tkinter和x27的意外行为;s网格嵌入在包含280多个元素的画布中,python,tkinter,Python,Tkinter,我想显示很多缩略图,并且能够根据缩略图的内容对它们执行不同的操作。为此,我从中选取了示例,并将标签放在嵌入网格的第一列中,将图像放在第二列中。作为示例缩略图,您可以下载此缩略图并将其重命名为160x120.jpg import Tkinter as tk from PIL import Image, ImageTk class Example(tk.Frame): def __init__(self, root): tk.Frame.__init__(self, ro

我想显示很多缩略图,并且能够根据缩略图的内容对它们执行不同的操作。为此,我从中选取了示例,并将标签放在嵌入网格的第一列中,将图像放在第二列中。作为示例缩略图,您可以下载此缩略图并将其重命名为
160x120.jpg

import Tkinter as tk
from PIL import Image, ImageTk

class Example(tk.Frame):
    def __init__(self, root):

        tk.Frame.__init__(self, root)
        self.canvas = tk.Canvas(root, borderwidth=0, background="#ffffff")
        self.frame = tk.Frame(self.canvas, background="#ffffff")
        self.vsb = tk.Scrollbar(root, orient="vertical", command=self.canvas.yview)
        self.canvas.configure(yscrollcommand=self.vsb.set)

        self.vsb.pack(side="right", fill="y")
        self.canvas.pack(side="left", fill="both", expand=True)
        self.canvas.create_window((4,4), window=self.frame, anchor="nw", 
                                  tags="self.frame")

        self.frame.bind("<Configure>", self.OnFrameConfigure)

        self.photos = []
        self.imgs = []
        self.images = []
        self.lbls = []

        self.populate()

    def populate(self):
        '''Put in some fake data'''

        # n_thumbs = 100 : As expected, one label and one image per row.
        # n_thumbs = 300 : Images are only displayed up to the 278th.
        # n_thumbs = 600 : Just 63 images are displayed. Two labels per row.

        n_thumbs = 100

        for i in range(n_thumbs):
            lbl = tk.Label(self.frame, text="img " + str(i), width=10)
            lbl.grid(row=i, column=0)
            photo = Image.open("160x120.jpg")
            img = ImageTk.PhotoImage(photo)
            image = tk.Label(self.frame, image=img)
            image.grid(row=i, column=1)
            self.lbls.append(lbl)
            self.photos.append(photo)
            self.images.append(image)
            self.imgs.append(img)

    def OnFrameConfigure(self, event):
        '''Reset the scroll region to encompass the inner frame'''
        self.canvas.configure(scrollregion=self.canvas.bbox("all"))

if __name__ == "__main__":
    root=tk.Tk()
    Example(root).pack(side="top", fill="both", expand=True)
    root.mainloop()
将Tkinter作为tk导入
从PIL导入图像,ImageTk
类示例(tk.Frame):
定义初始化(自,根):
tk.Frame.\uuuu init\uuuu(self,root)
self.canvas=tk.canvas(根,borderwidth=0,background=“#ffffffff”)
self.frame=tk.frame(self.canvas,background=“#ffffffff”)
self.vsb=tk.Scrollbar(root,orient=“vertical”,command=self.canvas.yview)
self.canvas.configure(yscrollcommand=self.vsb.set)
自包装(side=“right”,fill=“y”)
self.canvas.pack(side=“left”,fill=“both”,expand=True)
self.canvas.create_window((4,4),window=self.frame,anchor=“nw”,
tags=“self.frame”)
self.frame.bind(“,self.OnFrameConfigure)
self.photos=[]
self.imgs=[]
self.images=[]
self.lbls=[]
self.populate()
def填充(自我):
''输入一些假数据''
#n_thumbs=100:如预期,每行一个标签和一个图像。
#n_thumbs=300:图像仅在278之前显示。
#n_thumbs=600:仅显示63幅图像。每行两个标签。
n_拇指=100
对于范围内的i(n_拇指):
lbl=tk.Label(self.frame,text=“img”+str(i),宽度=10)
lbl.grid(行=i,列=0)
photo=Image.open(“160x120.jpg”)
img=ImageTk.PhotoImage(照片)
image=tk.Label(self.frame,image=img)
image.grid(行=i,列=1)
self.lbls.append(lbl)
self.photos.append(照片)
self.images.append(图像)
self.imgs.append(img)
def OnFrameConfigure(自我,事件):
''重置滚动区域以包含内部框架''
self.canvas.configure(scrollregion=self.canvas.bbox(“全部”))
如果名称=“\uuuuu main\uuuuuuuu”:
root=tk.tk()
示例(root).pack(side=“top”,fill=“both”,expand=True)
root.mainloop()
现在,如果您设置
n_thumbs=100
,一切都会按预期工作,即每行有一个标签和一个图像

如果设置
n_thumbs=300
,列表将以第278幅图像突然结束

如果设置
n_thumbs=600
,则仅显示63个图像,但您仍可以向下滚动到上一个图像之后。此外,每行突然有两个标签


如何解释这些影响?如何使用Tkinter在一个网格中显示300多个图像?

我不知道事实,但我猜您已经超出了tk画布的限制。对于120像素高的图像,可以在包含帧超过32k(32767)像素高之前垂直显示272个图像。画布不能大于32767x32767,这可能是一个硬限制。或者坐标被限制在-32767到+32767之间。如果你的一些缩略图不是完全120像素高,这可能解释了你看到的278像素的限制。我在OSX系统上看到了一个稍微不同的限制

再说一次,我不知道这是事实,但似乎有可能


如果这是一个硬限制,只需稍加努力,您一次只能显示一个屏幕,并且只有在滚动到视图中时才能加载新图像(并且您可以销毁已滚动到视图外的图像)。并且,不要使用嵌入式框架,而是直接在画布上绘制图像

看看传统知识的来源,我认为你是对的。坐标和尺寸的类型是int,这意味着这是一个硬限制。为了解决这个问题,某种寻呼机似乎很合适。谢谢你给我指明了正确的方向!