python - 使用 Tkinter 在一个窗口中随机显示图像

标签 python tkinter cross-platform

我试图在每 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)

谢谢!

-乔纳森

编辑:对布莱恩奥克利的回应: 我尝试了您的建议,这看起来像是解决方案。

该函数每 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('.')),但会使代码更难阅读。除了可能使用更多周期外,我没有看到任何缺点?我没有看到内存随着时间的推移而增加,这对我来说很重要。

这是代码,谢谢 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()

最佳答案

您需要删除无限循环——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 每次都创建一个新的标签小部件——在函数外部创建一次标签,每次调用时只需更改图像。

关于python - 使用 Tkinter 在一个窗口中随机显示图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23569738/

相关文章:

python:numpy函数扩展多个矩阵

python - 在 Pandas 中使用 group by 进行转换

python - 使用集成的小部件。 PyQT 与 Tkinter

python - 即使声明了类名也未定义

c++ - Qt 是否属于 C++ 库?如果不是库,你会如何对 QT 进行分类?

python - Django Python - 如何在一个 HTML 模板中显示来自不同表格的信息

python - 在 tkinter 中创建一个简单的应用程序来显示 map

python - 在 NewWindow 上创建图像还为时过早

java - Gradle-build JavaFX 项目无法在 Windows 中运行

angular - 当我尝试更新 NativeScript 项目时收到错误消息