为什么图像不显示在 tkinter 中使用 if 条件?

Why is the image not showing in the tkinter using if conditions?

    from tkinter import *
from tkinter import ttk
from PIL import ImageTk ,Image

win=tkinter.Toplevel()

wrapper=Frame(win, bd=4, relief=RIDGE, bg="crimson")
wrapper.place(x=0, y=80, width=465, height=625)
wrapper3=Frame(win, bd=4, relief=RIDGE, bg="crimson")
wrapper3.place(x=950, y=80, width=465, height=625) 
wrapper3_title=Label(wrapper3, text="Selected Data", bg="crimson", fg="white", font=("times new roman",30,"bold"))
wrapper3_title.grid(row=0,column=0,padx=20, pady=10)
wrapper2=Frame(win, bd=4, relief=RIDGE, bg="crimson")
wrapper2.place(x=465, y=80, width=485, height=625) 

ent8=StringVar()


def code():
    btn1.destroy()
    add=StringVar()
    sub=StringVar()
    pro=StringVar()

    img=ImageTk.PhotoImage(Image.open("Amritsar.jpg"))
    Label2= Label(wrapper2, image=img)
    Label2.grid(row=0, column=0, padx=10, pady=5, sticky='w')

    def Find():
        add.set(float(ent00.get())+float(ent01.get()))
        sub.set(float(ent00.get())-float(ent01.get()))
        pro.set(float(ent00.get())*float(ent01.get()))

    ent00=Entry(wrapper, width=15)
    ent00.grid(row=4, column=1, padx=10, pady=10, sticky='w')
    ent01=Entry(wrapper, width=15)
    ent01.grid(row=5, column=1, padx=10, pady=10, sticky='w')

    lbl8=Label(wrapper, text="Add", bg="crimson", fg="white", font=("times new roman",15,"bold")).grid(row=6, column=0, padx=20, pady=10, sticky='w')
    ent8=Entry(wrapper, textvariable=add, width=15, state='readonly')
    ent8.grid(row=6, column=1, padx=10, pady=10, sticky='w')

    lbl15=Label(wrapper, text="Subtract", bg="crimson", fg="white", font=("times new roman",15,"bold")).grid(row=7, column=0, padx=20, pady=10, sticky='w')
    ent15=Entry(wrapper, textvariable=sub, width=15, state='readonly')
    ent15.grid(row=7, column=1, padx=10, pady=10, sticky='w')

    lbl9=Label(wrapper, text="Product", bg="crimson", fg="white", font=("times new roman",15,"bold")).grid(row=8, column=0, padx=20, pady=10, sticky='w')
    ent9=Entry(wrapper, textvariable=pro, width=15, state='readonly')
    ent9.grid(row=8, column=1, padx=10, pady=10, sticky='w')

    btn = Button(wrapper, text = 'Calculate', command=Find, bd = '5', width=15, height=2)
    btn.grid(row=11, column=1, padx=20, pady=10)

def img():  
    if ent8.get()=="4":
        img=ImageTk.PhotoImage(Image.open("Amritsar.jpg"))
        Label2= Label(wrapper3, image=img)
        Label2.grid(row=0, column=2, padx=10, pady=5, sticky='w')
        print("Move ahead")
    else:
        print("Try again")

btn2 = Button(wrapper, text = 'Image', command=img, bd = '5', width=15, height=2)
btn2.grid(row=12, column=1, padx=20, pady=10)        

btn1 = Button(wrapper, text = 'OPEN CODE', command=code, bd = '5', width=20, height=2)
btn1.grid(row=11, column=1, padx=20, pady=10)

win.geometry("1400x700+250+250")
win.mainloop()

需要在 tkinter 上显示两张图片。之前在 wrapper2 中定义的那个显示空帧,而在得到 4 作为总和后必须出现在 wrapper3 中的那个根本不出现。此外,打印的输出是“再试一次”。为什么会这样?当总和为 4 时,它必须显示“向前移动”。

首先,糟糕的名字。
您的函数和 PhotoImage 都被命名为 img。将函数重命名为 def add_img()。 其次,查看您的代码,我不知道所有包装框架的用途是什么,为什么不根据计划容纳的内容来命名它们呢?这同样适用于所有小部件。 calc_btn 不是比 btn 更好的名字吗? img_btn 而不是 btn2?为什么你需要阅读更多的东西而不是名字才能知道什么是什么?

第三,你的代码中有两次ent8。一次作为 Label,一次作为 StringVar。

Tkinter 不断刷新您的 window 因此您需要保存您正在使用的图像。
就个人而言,我会在 class.

中完成所有这些

现在,使用您当前的代码,只需添加
loaded_img = ImageTk.PhotoImage(Image.open("Amritsar.jpg")) 在你的函数之前而不是使用你用来打开图像的变量,只需使用 Label(wrapper3, image=loaded_img)

如:

win = Toplevel()

wrapper=Frame(win, bd=4, relief=RIDGE, bg="crimson")
wrapper.place(x=0, y=80, width=465, height=625)
wrapper3=Frame(win, bd=4, relief=RIDGE, bg="crimson")
wrapper3.place(x=950, y=80, width=465, height=625)
wrapper3_title=Label(wrapper3, text="Selected Data", bg="crimson", fg="white", font=("times new roman",30,"bold"))
wrapper3_title.grid(row=0,column=0,padx=20, pady=10)
wrapper2=Frame(win, bd=4, relief=RIDGE, bg="crimson")
wrapper2.place(x=465, y=80, width=485, height=625)

ent8=StringVar()

loaded_img = ImageTk.PhotoImage(Image.open("Amritsar.jpg"))

编辑
这是完整的代码:

from tkinter import *
from tkinter import ttk
from PIL import ImageTk ,Image

win=Toplevel()

wrapper=Frame(win, bd=4, relief=RIDGE, bg="crimson")
wrapper.place(x=0, y=80, width=465, height=625)
wrapper3=Frame(win, bd=4, relief=RIDGE, bg="crimson")
wrapper3.place(x=950, y=80, width=465, height=625)
wrapper3_title=Label(wrapper3, text="Selected Data", bg="crimson", fg="white", font=("times new roman",30,"bold"))
wrapper3_title.grid(row=0,column=0,padx=20, pady=10)
wrapper2=Frame(win, bd=4, relief=RIDGE, bg="crimson")
wrapper2.place(x=465, y=80, width=485, height=625)

ent8=StringVar()

loaded_img = ImageTk.PhotoImage(Image.open("Amritsar.jpg"))
add_strvar = StringVar()
sub_strvar = StringVar()
pro_strvar = StringVar()

def code():
    btn1.destroy()

    Label2= Label(wrapper2, image=loaded_img)
    Label2.grid(row=0, column=0, padx=10, pady=5, sticky='w')

    def Find():
        add_strvar.set(float(ent00.get())+float(ent01.get()))
        sub_strvar.set(float(ent00.get())-float(ent01.get()))
        pro_strvar.set(float(ent00.get())*float(ent01.get()))

    ent00=Entry(wrapper, width=15)
    ent00.grid(row=4, column=1, padx=10, pady=10, sticky='w')
    ent01=Entry(wrapper, width=15)
    ent01.grid(row=5, column=1, padx=10, pady=10, sticky='w')

    lbl8=Label(wrapper, text="Add", bg="crimson", fg="white", font=("times new roman",15,"bold")).grid(row=6, column=0, padx=20, pady=10, sticky='w')
    ent8=Entry(wrapper, textvariable=add_strvar, width=15, state='readonly')
    ent8.grid(row=6, column=1, padx=10, pady=10, sticky='w')

    lbl15=Label(wrapper, text="Subtract", bg="crimson", fg="white", font=("times new roman",15,"bold")).grid(row=7, column=0, padx=20, pady=10, sticky='w')
    ent15=Entry(wrapper, textvariable=sub_strvar, width=15, state='readonly')
    ent15.grid(row=7, column=1, padx=10, pady=10, sticky='w')

    lbl9=Label(wrapper, text="Product", bg="crimson", fg="white", font=("times new roman",15,"bold")).grid(row=8, column=0, padx=20, pady=10, sticky='w')
    ent9=Entry(wrapper, textvariable=pro_strvar, width=15, state='readonly')
    ent9.grid(row=8, column=1, padx=10, pady=10, sticky='w')

    btn = Button(wrapper, text = 'Calculate', command=Find, bd = '5', width=15, height=2)
    btn.grid(row=11, column=1, padx=20, pady=10)


def add_img():
    if add_strvar.get() == "4.0":
        Label2= Label(wrapper3, image=loaded_img)
        Label2.grid(row=0, column=2, padx=10, pady=5, sticky='w')
        print("Move ahead")
    else:
        print("Try again")

btn2 = Button(wrapper, text = 'Image', command=add_img, bd = '5', width=15, height=2)
btn2.grid(row=12, column=1, padx=20, pady=10)

btn1 = Button(wrapper, text = 'OPEN CODE', command=code, bd = '5', width=20, height=2)
btn1.grid(row=11, column=1, padx=20, pady=10)

win.geometry("1400x700+250+250")
win.mainloop()

编辑 2
代码更改为使用 classes:

from tkinter import *
from tkinter import ttk
from PIL import ImageTk ,Image


class ImageCalculator:
    def __init__(self, img_path):
        self.window = Toplevel()
        self.window.geometry("1400x700+250+250")
        self.mainframe = Frame(self.window)
        self.mainframe.pack(expand=True, fill=BOTH)
        self.bg_color = 'crimson'

        frame_settings = {'master': self.mainframe, 'bd': 4,
                          'relief': RIDGE, 'bg': self.bg_color}
        frame_names = ('left', 'center', 'right')
        self.frames = {name: Frame(**frame_settings) for name in frame_names}

        frame_height = 625
        init_y = 80
        frame_widths = {'left': 465, 'center': 485, 'right': 465}
        x = 0
        for name in frame_names:
            frame_width = frame_widths[name]
            self.frames[name].place(x=x, y=init_y, width=frame_width,
                                    height=frame_height)
            x += frame_width
        self.setup_right_wrapper()
        self.code_btn = self.setup_left_wrapper()

        self.loaded_image = ImageTk.PhotoImage(Image.open(img_path))

        self.add_strvar = StringVar()
        self.sub_strvar = StringVar()
        self.pro_strvar = StringVar()

    def setup_left_wrapper(self) -> Button:
        code_btn = Button(self.frames['left'], text='OPEN CODE', command=self.code,
                          bd='5', width=20, height=2)
        img_btn = Button(self.frames['left'], text='Image', bd='5', width=15,
                         height=2, command=self.add_img)

        code_btn.grid(row=11, column=1, padx=20, pady=10)
        img_btn.grid(row=12, column=1, padx=20, pady=10)

        return code_btn

    def setup_right_wrapper(self):
        right_frame_title = Label(self.frames['right'], text="Selected Data",
                                  bg=self.bg_color, fg="white",
                                  font=("times new roman",30,"bold"))
        right_frame_title.grid(row=0, column=0, padx=20, pady=10)

    def code(self):
        def Find():
            self.add_strvar.set(float(first_entry.get())
                                + float(second_entry.get()))
            self.sub_strvar.set(float(first_entry.get())
                                - float(second_entry.get()))
            self.pro_strvar.set(float(first_entry.get())
                                * float(second_entry.get()))

        self.code_btn.destroy()

        Label2 = Label(self.frames['center'], image=self.loaded_image)
        Label2.grid(row=0, column=0, padx=10, pady=5, sticky='w')

        left_frame = self.frames['left']
        first_entry = Entry(left_frame, width=15)
        second_entry = Entry(left_frame, width=15)

        # Settings of all labels
        lbl_settings = {'bg': self.bg_color, 'fg': 'white',
                        'font': ("times new roman", 15, "bold")}
        # Setting of all entry.
        entry_settings = {'width': 15, 'state': 'readonly'}

        add_lbl = Label(left_frame, text="Add", **lbl_settings)
        add_entry = Entry(left_frame, textvariable=self.add_strvar,
                          **entry_settings)

        sub_lbl = Label(left_frame, text="Subtract", **lbl_settings)
        sub_entry = Entry(left_frame, textvariable=self.sub_strvar,
                          **entry_settings)

        pro_lbl = Label(left_frame, text="Product", **lbl_settings)
        pro_entry = Entry(left_frame, textvariable=self.pro_strvar,
                          **entry_settings)

        calc_btn = Button(left_frame, text='Calculate', command=Find, bd='5',
                          width=15, height=2)

        # Widget placement.
        first_entry.grid(row=4, column=1, padx=10, pady=10, sticky='w')
        second_entry.grid(row=5, column=1, padx=10, pady=10, sticky='w')
        add_lbl.grid(row=6, column=0, padx=20, pady=10, sticky='w')
        add_entry.grid(row=6, column=1, padx=10, pady=10, sticky='w')
        sub_lbl.grid(row=7, column=0, padx=20, pady=10, sticky='w')
        sub_entry.grid(row=7, column=1, padx=10, pady=10, sticky='w')
        pro_lbl.grid(row=8, column=0, padx=20, pady=10, sticky='w')
        pro_entry.grid(row=8, column=1, padx=10, pady=10, sticky='w')
        calc_btn.grid(row=11, column=1, padx=20, pady=10)

    def add_img(self):
        if self.add_strvar.get() == "4.0":
            Label2 = Label(self.frames['right'], image=self.loaded_image)
            Label2.grid(row=0, column=2, padx=10, pady=5, sticky='w')
            print("Move ahead")
        else:
            print("Try again")


def main():
    img_calc = ImageCalculator('Amritsar.jpg')

    mainloop()


if __name__ == "__main__":
    main()

为标签设置图片后,您需要保留对该图片的引用。否则,它会在函数末尾被删除,并且您会丢失图像(已被垃圾回收)。

因此,当您定义标签时,只需添加一行将图像存储为标签的属性即可:

    img=ImageTk.PhotoImage(Image.open("Amritsar.jpg"))
    Label2= Label(wrapper2, image=img)
    Label2.grid(row=0, column=0, padx=10, pady=5, sticky='w')
    Label2.dontloseit = img

Label2 小部件现在有一个名为 .dontloseit 的无意义属性,用于保存图像。现在,它不会被收集,它会显示在你的 tkinter 小部件中。

这是 tkinter 的特点之一。