How to update the image in tkinter class by key event binding?

Viewed 306

How to display the next image and previous image when the right arrow or left arrow key is pressed? I have done this in a simple example when I don't define the Example class but failed when I want to do it in the example code below. I have defined two static methods inside the Example class to bind the left arrow and right arrow to the GUI. It works well in printing the event but I don't know how to update the image option of the label by configure(image = next_photo) and configure(image = previous_photo). Here is a part of my code:

current = 0
class Example(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)
        self.master.bind('<Left>', self.left_key)
        self.master.bind('<Right>', self.right_key)
        image = Image.open(image_list[0])
        image = image.resize((800, 600),Image.ANTIALIAS)
        photo = ImageTk.PhotoImage(image)
        self.logo = tk.Label(self, text="Logo", background="orange")
        self.logo2 = tk.Label(self, image = photo)
        ############################################# ScrolledText ##########################################
        self.edit_space = tkst.ScrolledText(
                master = self,
                wrap   = 'word',  # wrap text at full words only
                width  = 50,      # characters
                height = 10,      # text lines
                bg='beige'        # background color of edit area
        )
        self.other1 = tk.Label(self, background="purple")
        self.other2 = tk.Label(self, background="yellow")
        self.other3 = tk.Label(self, background="pink")
        self.other4 = tk.Label(self, background="gray")
        self.main = tk.Frame(self, background="blue")
        self.logo.grid(row=0, column=0, rowspan=1, sticky="nsew")
        self.logo2.grid(row=1, column=0, rowspan=1, sticky="nsew")
        self.other1.grid(row=0, column=1, sticky="nsew")
        self.other2.grid(row=0, column=2, sticky="nsew")
        self.other3.grid(row=1, column=1, sticky="nsew")
        self.other4.grid(row=1, column=2, sticky="nsew")
        self.edit_space.grid(row=2, column=0, sticky="nsew")
        self.main.grid(row=2, column=2, columnspan=2, rowspan=6)
        for row in range(8):
            self.grid_rowconfigure(row, weight=1)
        for col in range(3):
            self.grid_columnconfigure(col, weight=1)
    @staticmethod
    def left_key(event):
        print(str(event) + " key pressed")
        global current, image_list
        if not (0 <= current + 1 < len(image_list)):
            print("This is the first image")
            return
        current += 1
        image = Image.open(image_list[current])
        image = image.resize((800, 600),Image.ANTIALIAS)
        photo = ImageTk.PhotoImage(image)
        # self.logo2 = tk.Label(self, image = photo)
        #self.logo2.configure(image = photo)
    @staticmethod
    def right_key(event):
        print(str(event) + " key pressed")
        global current, image_list
        if not (0 <= current - 1 < len(image_list)):
            print("This is the last image")
            return
        current -= 1
        image = Image.open(image_list[current])
        image = image.resize((800, 600),Image.ANTIALIAS)
        photo = ImageTk.PhotoImage(image)
        # self.logo2 = tk.Label(self, image = photo)
        #self.logo2.configure(image = photo)
if __name__ == "__main__":
    root = tk.Tk()
    Example(root).pack(fill="both", expand=True)
    root.geometry("800x400")
    root.mainloop()
1 Answers

The main issue is that you create local variable photo inside __init__() and use it as the image of logo2. However photo will be destroyed after __init__() is executed which will cause no image is displayed.

In order to fix the problem:

  • use self.photo instead of photo
  • change the 2 static methods, left_key() and right_key(), to instance methods
  • set the image of logo2 inside left_key() and right_key(): self.logo2.configure(image=self.photo)

Furthermore, the checking of the value of current inside left_key() and right_key() may cause problem:

  • in left_key(), current > 0 should be checked
  • in right_key(), current < len(image_list)-1 should be checked

and the adjustment of current in these 2 methods is in wrong direction:

  • left_key() should decrease current
  • right_key() should increase current
Related