0

I am trying to display an image to the window based on a phrase. If the character in the phrase matches the name of the picture, it should be displayed on the window. If the phrase has more than one character, the picture related to the character after the current character should be displayed to the right of the current character's picture. How would I be able to make it so that a new side-by side picture duo shows up, this time showing the picture related to the second character on the left and the third character on the right, and so on? I tried using .after() but I am not sure where to place it.

Also, when I run the following code I get an index out of range error unless I use the break statement.but I can't seem to figure out what it is. Maybe using the after() method will fix it?

import tkinter as tk
from PIL import ImageTk, Image, ImageDraw, ImageFont
import time


def open_image():
    global i
    global image
    global img
    global image2
    global img2

    if i < len(phrase):

        if phrase[i] == " ":
            image = Image.open("Rest.jpg")
            img = ImageTk.PhotoImage(image)
            panel['image'] = img
        else:
            image = Image.open(phrase[i] + ".jpg")
            img = ImageTk.PhotoImage(image)
            panel['image'] = img
        if phrase[i + 1] != None and phrase[i + 1] != " ":
            image2 = Image.open(phrase[i + 1] + ".jpg")
            panel2['image2'] = img2
        else:
            image2 = Image.open("Rest1.jpg")
            panel2['image2'] = img2

        i += 1
        window.after(2000, open_image)
    else:
        window.destroy()

# --- main ---

i = 0
phrase = " trac "

window = tk.Tk()

panel = tk.Label(window) # without image
panel.pack(side = "left", fill = "both", expand = "1", padx = 5, pady = 5)
panel2 = tk.Label(window)
panel2.pack(side = "left", fill = "both", expand = "1", padx = 5, pady = 5)                 

# use it after creating Label so it can set image 
open_image()

window.mainloop()
poromazh
  • 29
  • 5
  • Use the universal widget [`after()`](http://web.archive.org/web/20190222214221id_/http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/universal.html) method to schedule a call to a function that changes the picture after the specified delay. – martineau Sep 02 '19 at 23:00
  • where should I put it? Would I have to remove the for loop in the function? – poromazh Sep 02 '19 at 23:32
  • Yes, you would need to get rid of the `for` loop. You would probably need to call `after()` in the `command` callback function of a `Button` or maybe a `Menu` widget. GUI programming is based on a different paradigm than the sequential procedural sort of programming you're probably used to doing, everything has to happen in the context of the main user-event processing loop (`mainloop()` in `tkinter`). See the accepted answer to the question [Tkinter — executing functions over time](https://stackoverflow.com/questions/9342757/tkinter-executing-functions-over-time). – martineau Sep 02 '19 at 23:42
  • Note that essentially what you're wanting to do is (very slow) animation. – martineau Sep 02 '19 at 23:47
  • I've editied it, would you mind taking a look? I'm getting the same problem I had before - a string index out of range error at the line: if phrase[i + 1] != None and phrase[i + 1] != " ": – poromazh Sep 02 '19 at 23:54
  • `after()` needs function's name without `()` - it is called "callback" - `window.after(2000, open_image)` – furas Sep 03 '19 at 00:02
  • You need to provide the code for an [mcve] in your question so that others can (easily) work on it. In this case that means also including the images required for it to run. You can add them to your question via the "Image" button near the top of the question editor here or by typing Cntrl-G. – martineau Sep 03 '19 at 00:03
  • you load new image but you don't change images in `Label`. – furas Sep 03 '19 at 00:04
  • @furas should I place the lines of code for img and panel above window.after in the if statement? – poromazh Sep 03 '19 at 00:15
  • @martineau I have added links to the images – poromazh Sep 03 '19 at 00:15
  • poromazh: That's better. However I won't be able to a work on this for a while, but will check back later and see where things stand — maybe someone else will provide an acceptable answer before then... – martineau Sep 03 '19 at 00:22
  • @furas I added the code to add the second picture to the right of the first picture, but I get an error saying that img2 is not defined. I did it the same way that img was done; can I not place them side by side again – poromazh Sep 03 '19 at 00:44
  • `img2` is not defined because you forgot `img2 = ImageTk.PhotoImage(image2)` – furas Sep 03 '19 at 00:45
  • @martineau I believe I am good and can work from here, thank you for your help! – poromazh Sep 03 '19 at 00:50

1 Answers1

0

I reduced code to create working example.

after() uses function's name without ()

open_image() loads image, assigns to global variable (to resolve problem with bug in PhotoImage) and changes image in Label

At start I create Label without image and open_image() adds first image, and later it change this image to new one.

import tkinter as tk
from PIL import Image, ImageTk

# --- functions ---

def open_image():
    global i
    global image
    global img 

    if i < len(phrase): # check at the beginning to resolve problem with `IndexError: list index out of range`

        image = Image.open(phrase[i] + ".jpg")
        img = ImageTk.PhotoImage(image)
        panel['image'] = img

        i += 1
        window.after(2000, open_image)
    else:
        #window.quit()
        window.destroy()

# --- main ---

i = 0
phrase = " trac "

window = tk.Tk()

panel = tk.Label(window) # without image
panel.pack()

# use it after creating Label so it can set image in existing label
open_image()

window.mainloop()
furas
  • 134,197
  • 12
  • 106
  • 148