1

我想显示很多缩略图并能够对它们进行不同的操作,具体取决于缩略图的内容。为此,我以在 Tkinter 中将滚动条添加到一组小部件中为例,并将标签放在嵌入式网格的第一列中,将图像放在第二列中。作为示例缩略图,您可以下载此图像并将其重命名为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()

现在,如果您设置n_thumbs = 100,一切都会按预期工作,即每行有一个标签和一个图像。

如果设置n_thumbs = 300,列表会突然以第 278 张图像结束。

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

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

4

1 回答 1

2

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

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

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

于 2013-11-14T21:55:19.410 回答