当前位置: 首页 > 知识库问答 >
问题:

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

农鸿德
2023-03-14

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

然而,它这样做的方式是当鼠标点击窗口时,它调用一个函数来关闭小部件。

我遇到的问题是如何调用这个函数,或者在没有事件的情况下关闭小部件。有什么建议吗?

这就是我现在拥有的。这显然不起作用,因为它卡在根中。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秒调用一次,并创建一个窗口,但图像未放置在窗口中。

是不是我没有访问根?我如何获得访问权限?

以下是我目前的情况:

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()

谢谢你!!

解决方案编辑:我没有更改代码,因此标签只创建一次,因此每次调用都会创建一个标签。我没有这样做,因为这可以应用于许多其他变量(对于exmaple,dirlist=os.listdir('.')),但会使代码更难阅读。除了可能使用更多的循环外,我没有看到任何缺点?我没有看到记忆随着时间的推移而增加,这对我来说是最重要的。

这里是代码,谢谢布莱恩·奥克利帮助我!!

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()

共有2个答案

唐阳泽
2023-03-14

布莱恩·奥克利找到了错误的根本原因,这一切都归功于他。我稍微清理了你的代码。自从我运行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()
吕永寿
2023-03-14

您需要删除无限循环——tkinter已经有一个内置循环。相反,在之后使用定期调用函数:

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()

此外,您不需要每次都创建一个新的标签小部件——在函数之外创建一次标签,每次调用图像时只需更改一次。

 类似资料:
  • 问题内容: 我想让我的程序显示在任务栏中,但仍然没有传统的Windows寄宿生。我该怎么办?我知道 self.overrideredirect(1) ,但是这从任务栏中删除了我的程序。 这适用于Windows 7。 问题答案: 我没有断言这是“正确”的方法,但是请看这是否对您有用:

  • 问题内容: 我正在尝试通过py2exe创建一个exe。该程序正在使用Tkinter显示类似弹出窗口的窗口。问题是,当我像这样运行安装程序时,一切正常: 但是当我尝试制作一个文件的exe时失败: 实际上,最终exe可以正常运行,但是不会显示任何窗口。我已经阅读过Windows 7上的bundle_files = 1可能存在问题,但我也尝试了bundle_files = 2来达到同样的效果。这是我的m

  • 我有一个docker容器,它可以打开一个tkinter窗口,但它一直崩溃,因为它无法连接到主机的显示器。本文给出的答案建议将X-11套接字绑定到容器< code >-v/tmp/. X11-unix:/tmp/. X11-UNIX:ro ,并将其显示环境变量设置为主机< code>-e DISPLAY=$DISPLAY的显示环境变量,但由于这两个变量都是UNIX特定的路径/变量,因此它们在其他操作

  • 更新:找到解决方案并更新为自我回答。 我在一个目录中有20个jpg图像。使用Python 3.7 Tkinter 8.6。10.我访问它们,调整大小并将它们显示在网格的主窗口中。网格有12行x 5列=60帧。第1行中的所有帧都有标签,标签中填充了大小调整后的图像。第2行中的所有框架都有带有文本“放大”的标签。第3行中的所有框架都有带有文本“Select”的标签。这种模式重复。 点击"放大"按钮,我

  • 问题内容: 我正在尝试使用wunderground的api,Leaflet和Cloudmade将天气图标显示在地图标记中。我已经显示了文本和带有图标图像的变量,但是我不确定如何显示它。这是我的代码: 我尝试了一下但没有成功: 有什么建议? 问题答案: 标记的bindPopup方法仅将HTML内容作为字符串,因此您还需要在标记周围加上引号-类似于 应该为您工作。

  • 问题内容: 我正在使用以下代码来启动.cmd文件: 它工作正常,但我实际上希望看到cmd.exe窗口正在运行。如何显示?任何帮助将不胜感激! 问题答案: 除了运行路径外,请尝试实际运行,但是使用build in 命令启动新的命令窗口。您可以通过在命令提示符下输入以下命令来查看完整的命令行参数集: 在您的情况下,您可能想要执行类似以下命令的操作: