首页 > 解决方案 > 如何在 tkinter 中替换背景图像?

问题描述

我有一个正在循环的脚本,一旦满足条件,就会将图像添加到我的 Tkinter 窗口中。我可以在 Tkinter 中添加和调整图像大小,但是当我通过 while 循环时,我想做的是替换图像(或者更确切地说,只是在前一个图像之上添加另一个图像)。然而,虽然Images被重新定义为“greencar.jpg”,但实际图像并未发布在窗口中。

import tkinter as tk
from tkinter import *
from PIL import ImageTk, Image

Images=()
class Example(Frame):
    global Images
    def __init__(self, master, *pargs):
        Frame.__init__(self, master, *pargs)



        self.image = Image.open(Images)
        self.img_copy= self.image.copy()


        self.background_image = ImageTk.PhotoImage(self.image)

        self.background = Label(self, image=self.background_image)
        self.background.pack(fill=BOTH, expand=YES)
        self.background.bind('<Configure>', self._resize_image)

    def _resize_image(self,event):

        new_width = event.width
        new_height = event.height

        self.image = self.img_copy.resize((new_width, new_height))

        self.background_image = ImageTk.PhotoImage(self.image)
        self.background.configure(image =  self.background_image)

def main():
    global Images
    x=0
    root.update_idletasks()
    while x<100000:
        x+=1
        if x == 500:
            Images='mountain.jpg'
            e = Example(root)
            e.pack(fill=BOTH, expand=YES)
            root.update_idletasks()

        if x == 5000:
            Images='greencar.jpg'
            e = Example(root)
            e.pack(fill=BOTH, expand=YES)
            root.update_idletasks()




root = tk.Tk()
root.geometry('600x600')
main()
root.mainloop()

编辑:所以尝试 Saad 的解决方案效果非常好,但我试图通过实现几个函数和第二个循环来进一步扩展它。

import tkinter as tk
from tkinter import *
from PIL import ImageTk, Image

Images= "mountain.jpg"


class Example(Frame):

    def __init__(self, master, *pargs):
        Frame.__init__(self, master, *pargs)

        self.image = Image.open(Images)
        self.img_copy= self.image.copy()

        self.background_image = ImageTk.PhotoImage(self.image)

        self.background = Label(self, image=self.background_image)
        self.background.pack(fill=BOTH, expand=YES)
        self.background.bind('<Configure>', self._resize_image)

    def _resize_image(self,event):
        new_width = event.width
        new_height = event.height

        self.image = self.img_copy.resize((new_width, new_height))

        self.background_image = ImageTk.PhotoImage(self.image)
        self.background.configure(image =  self.background_image)

    def change_image(self, file):
        """Change background image of the window."""
        size = (self.winfo_width(), self.winfo_height())
        self.image = Image.open(file).resize(size)
        self.background_image = ImageTk.PhotoImage(self.image)
        self.background.configure(image=self.background_image)


def add(x):
    return x+3

def subtract(x):
    return x-1

def check_image(x=0):
    x=add(x)
    if x >= 1000:
        return # Break the loop
    if x == 50:
        e.change_image('mountain.jpg')
    elif x == 500:
        e.change_image('greencar.jpg')
    print(x)
    root.after(1, check_image,subtract(x))

def loop():
    while True:
        question=input('go again?')
        if question == 'n':
            break
        check_image(x=0)


root = tk.Tk()
root.geometry('600x600')
e = Example(root)
e.pack(fill=BOTH, expand=YES)
loop()
root.mainloop()

所以我想要的是让用户再次通过循环的选项。所以我做了另一个函数来做到这一点。但是,check_image()不再循环。它在第一次迭代时停止。如果我打破了我的时间loop()(通过输入'n'),那么它将经历check_image()迭代,但是,图像不再更新。总之,我好像又把程序弄坏了,但我不太明白为什么。

标签: pythontkinter

解决方案


您的代码有几个问题需要解决。

  1. 要替换图像,您必须每次都创建一个PhotoImage带有参数的新实例,然后。与您的函数一样,您只是在同一窗口中创建一个新的小部件。file='new_image.png'self.background.configure(image=new_image_instance)mainExample

  2. 我不建议update_idletasks()在while循环中使用整个while循环可以用after(ms, func, *args)Tkinter的方法代替。

    def check_image(x=0):
        # Break the loop
        if x >= 100000: return
        if x == 500:
            e.change_image('mountain.jpg')
        elif x == 5000:
            e.change_image('greencar.jpg')
        root.after(1, check_image, x+1)
    
  3. 我认为最好只创建一个可以更改Example小部件图像的方法。

    def change_image(self, file):
        """Change background image of the window."""
        size = (self.winfo_width(), self.winfo_height())
        self.image = Image.open(file).resize(size)
        self.background_image = ImageTk.PhotoImage(self.image)
        self.background.configure(image=self.background_image)
    

完整代码:

import tkinter as tk
from tkinter import *
from PIL import ImageTk, Image

Images= "image.png"


class Example(Frame):

    def __init__(self, master, *pargs):
        Frame.__init__(self, master, *pargs)

        self.image = Image.open(Images)
        self.img_copy= self.image.copy()

        self.background_image = ImageTk.PhotoImage(self.image)

        self.background = Label(self, image=self.background_image)
        self.background.pack(fill=BOTH, expand=YES)
        self.background.bind('<Configure>', self._resize_image)

    def _resize_image(self,event):
        new_width = event.width
        new_height = event.height

        self.image = self.img_copy.resize((new_width, new_height))

        self.background_image = ImageTk.PhotoImage(self.image)
        self.background.configure(image =  self.background_image)
    
    def change_image(self, file):
        """Change background image of the window."""
        size = (self.winfo_width(), self.winfo_height())
        self.image = Image.open(file).resize(size)
        self.background_image = ImageTk.PhotoImage(self.image)
        self.background.configure(image=self.background_image)


def check_image(x=0):
    if x >= 100000: return # Break the loop
    if x == 500:
        e.change_image('mountain.jpg')
    elif x == 5000:
        e.change_image('greencar.jpg')
    root.after(1, check_image, x+1)
    

root = tk.Tk()
root.geometry('600x600')
e = Example(root)
e.pack(fill=BOTH, expand=YES)
check_image()
root.mainloop()

推荐阅读