在后台运行并与其他函数交互的倒计时计时器

2024-09-19 23:37:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直在四处寻找这个问题,但所有的解决方案都感觉非常复杂,即使这样,我也无法让它按照我想要的方式工作。我正在制作一个程序,从一个文件夹中随机打开一个图像,等待10秒,然后从同一个文件夹中打开另一个随机图像,并继续运行

很简单,我能够在一个While-True循环中完成它,并随着时间的推移完成“等待10秒”部分。sleep(10)。但是,我想有一个按钮,只要我想它重置它。我在tkinter中执行此操作,我有一个启动它的按钮,但当我添加一个按钮重置它时,我无法单击它,当我尝试时,程序崩溃。这是因为它是在时间。睡眠(10)和整个程序停止10秒。对于任何对代码感兴趣的人,请看这里

from tkinter import *
import random
import os
from PIL import Image
import time

root = Tk()

def AnmuViewer():
    while True:
        random_pic = (random.choice(os.listdir("D:/de_clutter/memez/anmu")))
        openPic = Image.open('D:/de_clutter/memez/anmu/' + random_pic)
        openPic.show()

        time.sleep(10)

        continue

def Restart():
    AnmuViewer()

start_btn = Button(root, text = "Start", command = AnmuViewer)
start_btn.pack()

next_btn = Button(root, text = 'Restart', command = Restart)
next_btn.pack()

root.mainloop()

我知道我不需要一个“重启”按钮,因为再次点击“启动”按钮也会做同样的事情。不管怎样,“开始”按钮本身也是不可点击的

我已经研究过线程,所以我想做一个从10开始倒计时的函数,当它达到10时,AnmuViewer()会重新开始,这样我就可以在任何时候再次单击“开始”并从头重置整个代码。但我也没能做到。有什么建议吗


Tags: 图像import程序文件夹truetkinter时间sleep
2条回答

while与tkinter一起使用将导致mainloop()出现一些问题,并将冻结该问题。您应该使用不会冻结GUI的after(ms,func)。一个非常简单的代码可以做到这一点,请看这里:

from tkinter import *
from tkinter import filedialog
from PIL import ImageTk, Image
from glob import glob #for the path of the image
import random

root = Tk()

def anmuViewer():
    global cb
    choice = random.choice(all_img) #random choice of image from the list of img
    cur = ImageTk.PhotoImage(file=choice) #make an image object
    img_label.config(image=cur) #changing the image on the label
    img_label.img = cur #keeping a reference to the image

    cb = root.after(10000,anmuViewer) #repeating the function every 10 second

def restart(): #reset func from Roblochons code
    global cb
    if cb is not None:
        root.after_cancel(cb)
        cb = None
    anmuViewer()

path = filedialog.askdirectory(title='Choose the directory with images') #ask the directory with the image.

png = glob(path+'/*.png') #pick all the png image
jpg = glob(path+'/*.jpg') #pick all the jpg image
all_img = png + jpg #concatenate both the list

img_label = Label(root) #image label, later to be configured
img_label.pack()

start_btn = Button(root, text = "Start", command=anmuViewer)
start_btn.pack(padx=10,pady=10)

next_btn = Button(root, text = 'Restart', command=restart)
next_btn.pack(padx=10,pady=10)

root.mainloop()

我已经用注释解释了代码,以便在移动中更容易理解。我没有假设图像的路径,所以我正在动态地选择路径,如您所见。代码看起来很长,因为为了更好地理解,我简化了大多数代码行

无论如何,您需要调整图像大小,使其适合每个人的屏幕,因为像素和屏幕分辨率因设备而异。看一看here

您可以在同一个按钮中组合startreset,但也可以添加一个调用相同函数的重置按钮(注释代码)。 也就是说,启动时,系统将重置为其初始状态,此处callback值设置为None

大多数时候,使用tkinter.mainloop比使用自定义while循环更好。在GUI中使用time.sleep通常会导致灾难,因为它会在执行过程中阻止所有交互

我用一个text label替换了这些图像。为了简单起见,您必须更改它

import tkinter as tk
import random


def anmu_viewer():
    global cb
    random_pic = random.choice(images)
    lbl.config(text=random_pic)
    cb = root.after(10000, anmu_viewer)   # keep a reference of the callback

def reset():
    global cb
    if cb is not None:
        root.after_cancel(cb)             # cancel the callback
        cb = None                         # reset the reference to the callback to None
    anmu_viewer()


images = ['im1', 'im2', 'im3', 'im4', 'im5', 'im6']

root = tk.Tk()
cb = None    
lbl = tk.Label(root, text='')
lbl.pack()
start_btn = tk.Button(root, text="Start", command=reset)
start_btn.pack()
# reset_btn = tk.Button(root, text="Reset", command=reset)
# reset_btn.pack()

root.mainloop()

相关问题 更多 >