每隔n秒显示一个消息框后重复一个功能

时间:2017-04-11 03:56:30

标签: python multithreading tkinter setinterval

我想设置一个功能,在显示消息框后再次重复。 下面显示了一个简短的代码示例,即我想要做的事情

def setInterval(func,time,args):
    e = threading.Event()
    while not e.wait(time):
        func(args)

def foo(data):
    print data
    aa("what")
def aa(a):
    print(a)

tkMessageBox.showinfo("Regret","nope")

setInterval(foo,5,"fsrty")

一切都还可以,但问题只是一旦显示的杂物盒给出“没有响应错误”。任何人请帮助找出解决方案

2 个答案:

答案 0 :(得分:2)

你将需要使用.after方法,因为线程永远不能很好地运行这个tkinter,也不会使用while循环。

import Tkinter as tk
import TkMessageBox

def setInterval(func,time,args):
        func(args)
        root.after(time, setInterval(func, time, args))
root.tk.Tk()
root.withdraw()
def foo(data):
    print data
    aa("what")
def aa(a):
    print(a)

tkMessageBox.showinfo("Regret","nope")
setInterval(foo, 5, "fsrty")
root.mainloop()

答案 1 :(得分:0)

线程和Tk不能很好地混合,因为它们违反了仅使用来自一个线程的Tk的Tcl / Tk线程模型而且你的代码不起作用,因为你占用了主要的(一个且唯一的) )线程!

虽然您的打印功能会继续打印 - 因此GUI不负责任,您可以使用代码中的其他print轻松检查:

>>> print('**** Active threads: %d ****' % threading.active_count())
**** Active threads: 1 ****

所以你真正需要的就是创造另一个!

try:
    import tkinter as tk
    from tkinter import messagebox as msgbox
except ImportError:
    import Tkinter as tk
    import TkMessageBox as msgbox

import threading


def setInterval(func,time,args):
    e = threading.Event()
    while not e.wait(time):
        print('**** Active threads: %d ****' % threading.active_count())
        func(args)


def foo(data):
    print(data)
    aa("what")


def aa(a):
    print(a)


root = tk.Tk()

print('**** Active threads: %d ****' % threading.active_count())
thread = threading.Thread(target=setInterval, args=(foo, 5, "fsrty"))
msgbox.showinfo("Regret", "nope")
thread.start()

root.mainloop()

但是这是另一个问题 - 即使在你关闭GUI之后(当你转义mainloop时)线程仍在运行!因此,如果您想要实现简单的事情 - .after()是一个选项(快速和小的替代方案)。

但如果你很顽固或真的需要这个 - 创建(覆盖)线程对象的自定义子类,它可以让你更灵活地控制你的流程!

try:
    import tkinter as tk
    from tkinter import messagebox as msgbox
except ImportError:
    import Tkinter as tk
    import TkMessageBox as msgbox

import threading


class Thread(threading.Thread):
    def __init__(self):
        super(Thread, self).__init__()
        self.running = False
        self.function_to_execute = None
        self._stop = threading.Event()

    def start_thread(self, func, *args, **kwargs):
        self.function_to_execute = (func, args, kwargs)
        self.running = True
        self.start()

    def run(self):
        print('### STARTED ###')
        while self.running:
            try:
                print('### RUNNING ###')
                function, args, kwargs = self.function_to_execute
                function(*args, **kwargs)
            except:
                self.stop()

    def stop(self):
        print('### STOPPING ###')
        self.running = False
        self._stop.set()


def setInterval(func, time, args):
    e = threading.Event()

    e.wait(time)
    print('**** Active threads: %d ****' % threading.active_count())
    func(args)


def foo(data):
    print(data)
    aa('what')


def aa(a):
    print(a)


def clear():
    thread.stop()

    while True:
        try:
            thread.is_alive()
        except TypeError:
            root.destroy()
            print('### STOPPED ###')
            print('**** Active threads: %d ****' % threading.active_count())
            break


root = tk.Tk()

thread = Thread()
print('**** Active threads: %d ****' % threading.active_count())
msgbox.showinfo("Regret", "nope")
thread.start_thread(setInterval, foo, 5, 'fsrty')
root.protocol('WM_DELETE_WINDOW', clear)

root.mainloop()

如你所见 - 当我们在退出之前试图清理时,事情变得越来越复杂,但它确实有效!

<强>结论:

  • 对于简单的事情 - .after()是一个不错的选择!
  • 对于复杂且长期执行的事情 - threading是您的选择!

<强>链接: