问题描述
这是我第一天使用 tkinter,我想知道如何正确编码我所做的事情。
我想做的是一种透光镜,所以我想找到一种在画布上显示图片的方法,并有两个按钮,这样我就可以转到上一张或下一张。我存储图片的方式是使用 l
numpy 数组的列表,l
的大小为 n
,所以我有 n
图片并且它们的大小相同。于是我写了下面的代码:
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,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)
我知道那是糟糕的代码,而不是应该编写的方式。它工作正常,但我需要帮助来改进代码。
解决方法
你应该只把更新图片的代码放在display()
里面,在函数外面创建接口。那么就不需要递归了。
还需要一个全局变量来跟踪图像列表的当前索引。当点击 Next 或 Previous 按钮时,应该更新这个变量。
以下是修改后的示例:
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()