简体   繁体   中英

How to replace a background image in tkinter?

I have a script where I'm going through a loop, and once a condition is met, an image is added to my Tkinter window. I'm able to add and resize the image in Tkinter, however what I want to do is replace the image (or rather, just add another image on top of the previous one), as I go through my while loop. However, while Images is redefined as 'greencar.jpg', the actual image is not posted in the window.

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()

Edit: So trying Saad's solution works really nicely, but I tried to extend it one step further, by implementing a couple of functions and a second loop.

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()

So what I wanted was the option for the user to go through the loop again. So I made another function to do this. However, check_image() no longer loops. It stops at the first iteration. If I break my while in loop() (by typing 'n'), then it will go through the check_image() iterations, however, the images no longer update. In short, I seem to have broken the program again, but I don't quite understand why.

There are a couple of issues with your code that needs to be addressed.

  1. To replace the image you have to create a new instance of PhotoImage with file='new_image.png' argument every time and then self.background.configure(image=new_image_instance) . As in your main function, you are just creating a new Example widget in the same window.

  2. I don't recommend using update_idletasks() in a while loop instead the whole while loop can be replaced by after(ms, func, *args) method of 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. I think it would be best to just create a method that will change the image of the Example widget.

     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)

Complete Code:

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()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM