You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用icrawler爬取谷歌图片填充Tkinter按钮仅显示最后一张问题求助

问题原因

你猜测的Python垃圾回收相关问题是正确的。Tkinter的PhotoImage对象不会被绑定的按钮组件自动持有引用,当create_grid函数执行结束后,局部作用域内的img_1对象会被GC清理,仅最后一次赋值的图片对象可能因残留引用保留,因此仅显示最后一张图。

具体修复方案

只需在代码中手动保留所有图片对象的引用即可,同时修复你现有代码中「新爬取的图片不会被加载」的逻辑问题,修改点如下:

  1. 新增列表存储图片引用,避免被GC回收
  2. 每次爬取完成后重新读取本地图片文件夹,重置计数与布局参数
  3. 移除阻塞主循环的time.sleep,icrawler的crawl方法本身是同步的,执行完成后自动进入下一步,不需要额外等待

修复后的完整代码

from tkinter import *
from PIL import ImageTk,Image
from icrawler.builtin import GoogleImageCrawler
import os

fileLocation = "C:\\Python projects\\tkinter\\images\\"
root = Tk()
root.title("Product image search")
# 若favicon.ico不存在可注释下一行避免启动报错
root.iconbitmap("favicon.ico")
e = Entry(root, borderwidth=5)
e.grid(row=0, column=0, columnspan=5)

button_list = []
# 新增列表专门存储图片引用,避免被垃圾回收
image_refs = []

def create_grid():
    global button_list, image_refs
    # 先清空之前生成的按钮和图片引用,避免多次搜索叠加布局
    for btn in button_list:
        btn.destroy()
    button_list.clear()
    image_refs.clear()
    # 重新读取当前图片文件夹的最新文件
    fileList = os.listdir(fileLocation)
    length = len(fileList)
    i = 0
    rows = 0
    cols = 1
    while i < length:
        img_path = f"{fileLocation}{fileList[i]}"
        # 跳过非图片文件避免启动报错
        try:
            img_raw= Image.open(img_path)
        except:
            i += 1
            continue
        img_resize = img_raw.resize((200, 200), Image.ANTIALIAS)
        img_1 = ImageTk.PhotoImage(img_resize)
        img_btn = Button(image=img_1)
        img_btn.grid(row= rows, column= cols)
        button_list.append(img_btn)
        # 手动保存图片引用到全局列表
        image_refs.append(img_1)
        rows += 1
        if rows == 5:
            rows = 0
            cols += 1
        i += 1

def crawlerAction():
    google_crawler = GoogleImageCrawler(
        parser_threads=2,
        downloader_threads=4,
        storage={'root_dir': 'images'})
    google_crawler.crawl(keyword=e.get(), max_num=20)
    create_grid()

search_btn = Button(text="検査", command=crawlerAction)
search_btn.grid(row=0, column=3)

root.mainloop()

额外说明

如果你坚持要把create_grid的逻辑放到函数外部,只要把图片对象存到全局的列表里,同样可以解决显示问题,核心逻辑就是不要让PhotoImage对象的引用计数降到0被GC回收即可。

内容的提问来源于stack exchange,提问作者pepelord

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 22:57:03