我试图在一个窗口中随机显示图像,每3秒更改一次。我也希望它是跨平台的,因为我在Windows中开发,但它将在linux上运行。
目前我有这个工作代码,只需点击一下鼠标即可遍历目录的所有图像文件(下面的代码)
import os, sys, Tkinter, Image, ImageTk
def button_click_exit_mainloop (event):
event.widget.quit()
root = Tkinter.Tk()
root.bind("<Button>", button_click_exit_mainloop)
root.geometry('+%d+%d' % (-5,-5)) #controls where the window is
#gets list of file names in certain directory. In this case, the directory it is in
dirlist = os.listdir('.')
for f in dirlist:
try:
image1 = Image.open(f)
root.geometry('%dx%d' % (image1.size[0],image1.size[1]))
tkpi = ImageTk.PhotoImage(image1)
label_image = Tkinter.Label(root, image=tkpi)
label_image.place(x=0,y=0,width=image1.size[0],height=image1.size[1])
root.mainloop() # wait until user clicks the window
except Exception, e:
pass
然而,这样做的方法是当鼠标点击窗口时,它会调用一个函数来关闭窗口小部件。
我遇到的问题是如何调用此功能,或关闭小部件而不用事件。有什么建议吗?
这就是我现在拥有的。这显然不起作用,因为它卡在root.mainloop()中,但它显示了我一般的想法(下面的代码)
import os, sys, Tkinter, Image, ImageTk, random
root = Tkinter.Tk()
root.geometry('+%d+%d' % (-5,-5)) #controls where the window is
#gets list of file names in certain directory. In this case, the directory it is in
dirlist = os.listdir('.') #might not be in order, CHECK!!!
while True:
randInt = random.randint(0, 1)
image = Image.open(dirlist[randInt])
root.geometry('%dx%d' % (image.size[0],image.size[1]))
tkpi = ImageTk.PhotoImage(image)
label_image = Tkinter.Label(root, image=tkpi)
label_image.place(x=0,y=0,width=image.size[0],height=image.size[1])
root.mainloop()
time.sleep(3)
谢谢!
-Jonathan
编辑:对Bryan Oakley的回应: 我尝试了你的建议,这看起来像解决方案。每隔3秒调用一次该函数,并且正在创建一个窗口,但图像未放置在窗口中。
我是否无法访问root用户?我如何获得访问权限?
以下是我目前的情况:
import os, sys, Tkinter, Image, ImageTk, random
def changeImage():
#gets list of file names in certain directory. In this case, the directory it is in
dirlist = os.listdir('.') #might not be in order, CHECK!!!
#get random image
randInt = random.randint(0, 1)
image = Image.open(dirlist[randInt])
#set size to show, in this case the whole picture
root.geometry('%dx%d' % (image.size[0],image.size[1]))
#Creates a Tkinter compatible photo image
tkpi = ImageTk.PhotoImage(image)
#Put image in a label and place it
label_image = Tkinter.Label(root, image=tkpi)
label_image.place(x=0,y=0,width=image.size[0],height=image.size[1])
# call this function again in three seconds
root.after(3000, changeImage)
root = Tkinter.Tk()
root.geometry('+%d+%d' % (-5,-5)) #controls where the window is
changeImage()
root.mainloop()
谢谢!
解决方案编辑: 我没有更改代码,所以标签只创建一次,因此每次调用都会创建一个标签。我没有这样做,因为这可以应用于许多其他变量(dirlist = os.listdir(&#39;。&#39;)for exmaple),但会使代码更难阅读。除了使用更多周期之外,我没有看到任何不利之处?我没有看到记忆力随着时间的推移而增加,这对我来说非常重要。
这是代码,谢谢Bryan Oakley帮助我!!
import os, Tkinter, Image, ImageTk, random
def changeImage():
global tkpi #need global so that the image does not get derefrenced out of function
#gets list of file names in certain directory. In this case, the directory it is in
dirlist = os.listdir('.')
#get random image
randInt = random.randint(0, 1)
image = Image.open(dirlist[randInt])
#set size to show, in this case the whole picture
root.geometry('%dx%d' % (image.size[0],image.size[1]))
#Creates a Tkinter compatible photo image
tkpi = ImageTk.PhotoImage(image)
#Put image in a label and place it
label_image = Tkinter.Label(root, image=tkpi)
label_image.place(x=0,y=0,width=image.size[0],height=image.size[1])
# call this function again in 1/2 a second
root.after(500, changeImage)
tkpi = None #create this global variable so that the image is not derefrenced
root = Tkinter.Tk()
root.geometry('+%d+%d' % (-5,-5)) #controls where the window is
changeImage()
root.mainloop()
答案 0 :(得分:1)
你需要删除你的无限循环 - tkinter已经有一个内置的。相反,使用after
定期调用函数:
def changeImage():
<do whatever you want, such as swapping out images>
# call this function again in three seconds
root.after(3000, changeImage)
然后,在主程序中,您可以在调用mainloop
之前调用该函数:
root = Tkinter.Tk()
...
changeImage()
root.mainloop()
此外,每次都不需要changeImage
创建新的标签小部件 - 在函数外部创建一次标签,并且每次调用时都只需更改图像。
答案 1 :(得分:0)
所有信用都归功于BryanOakley,以找出错误的根本原因。我稍微清理了你的代码。自从我运行Python3以来,导入也发生了一些变化,但是想确保它能够正常运行。
import os, sys, tkinter, random # N.B. tkinter not Tkinter in py3
from PIL import Image, ImageTk # these are submodules in pillow py3
class Root(tkinter.Tk): # I buried this in a class. I prefer that for tkinter
def __init__(self):
super().__init__() # call Tk.__init__
self.CYCLEDELAY = 3000 # 3 second per cycle
# create and place the label once.
self.image_label = tkinter.Label(self)
self.image_label.place(x=0,y=0)
# call our function
self.changeImage()
def changeImage(self):
"""Change the image on a delay"""
dirlist = os.listdir('.')
image = Image.open(random.choice(dirlist))
# you had a funky method of getting a random member here. I cleaned it up
i_width, i_height = image.size
self.geometry("{}x{}".format(i_width,i_height))
# change root's geometry using string formatting (preferred)
self.image_label.configure(width=i_width, height=i_height)
# change the label's geometry using string formatting
self.tkpi = ImageTk.PhotoImage(image)
self.image_label.configure(image=self.tkpi)
# configure the label to use the PhotoImage
self.after(self.CYCLEDELAY,self.changeImage)
# loop!
root = Root()
root.mainloop()