【问题标题】:How to change images while code is running in Tkinter Python如何在 Tkinter Python 中运行代码时更改图像
【发布时间】:2021-08-04 19:00:56
【问题描述】:

我想在 tkinter 中制作图像分类器:中间会有图像底部的 2 个按钮 ["one; two"],当我按下第一个按钮时,图像将转到文件夹 "one "

我尝试了很多变种,但无法解决这个问题; here is example

import tkinter as tk
from PIL import ImageTk, Image
from os import listdir

size= 700, 700

window = tk.Tk()
window.title("Join")
window.geometry("700x700")
window.minsize(700,700)
window.maxsize(700,700)

bottomFrame = tk.Frame(window)
bottomFrame.pack(fill=tk.X, side=tk.BOTTOM)

for i in range(2):
    bottomFrame.columnconfigure(i, weight=1)

#commands
def one():
    print("one")
    im.save("one/"+ path)

def two():
    print("two")
    im.save("two/"+ path)

#loop

imagesList = listdir("all/")

for path in imagesList:

    print("test")

    im = Image.open("all/" + path)

    im.thumbnail(size, Image.ANTIALIAS)

    img = ImageTk.PhotoImage(im)

    label = tk.Label(window, image = img)

    label.pack(side = "top", fill = "both", expand = "true")

    bluebutton = tk.Button(bottomFrame, text="one", fg="blue", command=one)
    bluebutton1 = tk.Button(bottomFrame, text="two", fg="blue", command=two)

    bluebutton.grid(row=0, column=0, sticky=tk.W+tk.E)
    bluebutton1.grid(row=0, column=1, sticky=tk.W+tk.E)

    window.mainloop()

【问题讨论】:

  • “不能解决这个问题” - 你为什么不能呢?当你尝试时会发生什么?您是否收到错误,如果是,错误是什么?您没有收到错误消息,但没有显示图像吗?它是否显示错误的图像?还有什么?
  • 一/二函数的path从何而来?

标签: python tkinter


【解决方案1】:

你很接近!问题在于您的函数onetwo

请注意,我在这里使用了全局变量,因此我不必对您的代码进行太多更改 - 您应该将其包装在 class 中,并将变量作为成员引用,使用 self

def one():
    global im, img, label
    print("one")
    # can't do this, or you'll overwrite the image!
    #im.save("one/"+ path)
    im = Image.open("one/" + path)

    im.thumbnail(size, Image.ANTIALIAS)

    img = ImageTk.PhotoImage(im)
    label.configure(image=img)

def two():
    global im, img, label
    print("two")
    # can't do this, or you'll overwrite the image!
#    im.save("two/"+ path)
    im = Image.open("two/" + path)

    im.thumbnail(size, Image.ANTIALIAS)

    img = ImageTk.PhotoImage(im)
    label.configure(image=img)

让我们解释一下原因:

  • mainloop 是一个“阻塞”调用;程序此时停止

  • 按钮按下专门设计用于在此块期间触发功能。这种类型的“异步”设计在 UI 中很典型

  • 所以加载图片的部分代码,这部分:

    im = Image.open("all/" + path)

    im.thumbnail(size, Image.ANTIALIAS)

    img = ImageTk.PhotoImage(im)

    只被调用一次

  • 您可以在函数onetwo 中“保存”图像,但目前尚不清楚这是为了做什么。看起来它只是用一个/两个覆盖图像。请注意,变量path 只是巧合地在该函数中正确设置,因为它正在查找全局变量。您可能应该直接传递它

相反,我们可以简单地open 路径onetwo 中的图像,然后使用configure 更改标签上显示的图像。 Note that you usually need to keep some references around to Image and ImageTk objects when your program gets nontrivial, otherwise the garbage collector might start trashing your pictures before you can see them

【讨论】:

    【解决方案2】:

    首先,您不应创建标签和按钮并在for 循环内运行mainloop()。您应该在主块中创建标签和按钮,并在主块中运行mainloop()

    然后你需要创建一个函数来显示下一张图片。将图像保存到您想要的文件夹后,该函数应在one()two() 中执行。

    下面是修改后的代码:

    import tkinter as tk
    from PIL import ImageTk, Image
    from os import listdir
    
    size= 700, 700
    
    window = tk.Tk()
    window.title("Join")
    window.geometry("700x700")
    window.minsize(700,700)
    window.maxsize(700,700)
    
    bottomFrame = tk.Frame(window)
    bottomFrame.pack(fill=tk.X, side=tk.BOTTOM)
    
    for i in range(2):
        bottomFrame.columnconfigure(i, weight=1)
    
    #commands
    def next_image():
        global im, img, path
        if len(imagesList) > 0:
            path = imagesList.pop(0) # extract a image path from the list
            im = Image.open(src_dir + path)
            im.thumbnail(size, Image.ANTIALIAS)
            img = ImageTk.PhotoImage(im)
            label.config(image=img)
        else:
            label.config(text="No more image!", image="")
    
    def one():
        print("one")
        im.save("one/"+path)
        next_image() # show next image
    
    def two():
        print("two")
        im.save("two/"+path)
        next_image() # show next image
    
    src_dir = "all/"
    imagesList = listdir(src_dir) # load the image list
    
    # label for showing the image
    label = tk.Label(window)
    label.pack(side = "top", fill="both", expand="true")
    
    bluebutton = tk.Button(bottomFrame, text="one", fg="blue", command=one)
    bluebutton1 = tk.Button(bottomFrame, text="two", fg="blue", command=two)
    
    bluebutton.grid(row=0, column=0, sticky=tk.W+tk.E)
    bluebutton1.grid(row=0, column=1, sticky=tk.W+tk.E)
    
    # show the first image
    next_image()
    window.mainloop()
    

    建议使用shutil.move()函数来移动那些图像文件,而不是im.save()

    import shutil
    ...
    def one():
        print("one")
        #im.save("one/"+path)
        shutil.move(src_dir+path, "one/")
        next_image()
    
    def two():
        print("two")
        #im.save("two/"+path)
        shutil.move(src_dir+path, "two/")
        next_image()
    ...
    

    【讨论】:

      猜你喜欢
      • 2011-04-22
      • 1970-01-01
      • 1970-01-01
      • 2015-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多