0

This is my first day using tkinter, and I wanted to know how to properly code what I have done.

What I wanted to make was a kind of diaporama so I wanted to find a way to display pictures in a canvas and have two buttons so I could go to the previous picture or the following one. The way I stored pictures is using a list lof numpy arrays, with l of size n, so I have n pictures and they are the same size. So I wrote the following code:

from tkinter import *
import numpy as np
from PIL import Image, ImageTk


import sys
sys.setrecursionlimit(10000) #I increased the recursion limit because I had some issues

l = [(255*np.random.rand(50,50)).astype(np.uint8) for i in range(105)] #this is a random list in case you want to test the code

def next(i,n):
    if i == n-1:
        return 0
    else:
        return i+1

def previous(i,n):
    if i==0:
        return n-1
    else:
        return i-1



window = Tk()
window.geometry("200x100+900+500")

def display(i):
    
    #This is to clear my window at each iteration because I would like to keep the same window

    for widget in window.winfo_children():
        widget.destroy()

    array = l[i] #this is the i-th picture

    img =  ImageTk.PhotoImage(image=Image.fromarray(array),master = window)

    canvas = Canvas(window, width=48, height=48)
    canvas.place(x=10, y=20)
    canvas.create_image(0,0, anchor="nw", image=img)

    Label(window, text="Picture n°"+str(i), fg="black").place(x=5, y=0)

    Button(window, text ='Next',command=lambda: display(next(i,len(l)))).place(x=140, y=35)
    Button(window, text ='Previous',command = lambda: display(previous(i,len(l)))).place(x=70, y=35)
    window.mainloop()


display(0) 

I know that is bad code and not the way it should be written. It is working fine but I need help to improve the code please.

Axel
  • 129
  • 1
  • 6
  • @JacksonPro I cannot define ```l``` in the code because it is a list of pictures I have imported before. But you can take ```l = [(255*np.random.rand(50,50)).astype(np.uint8) for i in range(105)]``` for example. I edited the code. – Axel Dec 29 '20 at 14:48

1 Answers1

1

You should only put the code of updating the image inside display() and create the interface outside the function. Then recursion is not needed.

Also a global variable is required to keep track the current index to the image list. This variable should be updated when Next or Previous button is clicked.

Below is a modified example:

from tkinter import *
import numpy as np
from PIL import Image, ImageTk

l = [(255*np.random.rand(50,50)).astype(np.uint8) for i in range(105)] #this is a random list in case you want to test the code
current = 0

def display(dir):
    global current
    # update "current" based on "dir"
    current = (current + dir) % len(l)
    # show the "current" image
    image = ImageTk.PhotoImage(Image.fromarray(l[current]))
    imgbox.config(image=image, text=f"Picture n°{current}")
    imgbox.image = image  # keep a reference to avoid "image" from being garbage collected

window = Tk()
window.geometry("200x100+900+500")

# use a label for showing image and text together
imgbox = Label(window, fg="black", compound="bottom", width=70)
imgbox.place(x=5, y=0)

Button(window, text ='Next', command=lambda: display(+1)).place(x=150, y=35)
Button(window, text ='Previous', command=lambda: display(-1)).place(x=80, y=35)

display(0) # show first image
window.mainloop()
acw1668
  • 40,144
  • 5
  • 22
  • 34