Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 每n秒显示一个消息框后重复一个功能_Python_Multithreading_Tkinter_Setinterval - Fatal编程技术网

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

Python 每n秒显示一个消息框后重复一个功能,python,multithreading,tkinter,setinterval,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("Regr

我想设置一个函数,以便在显示消息框后再次重复。 下面是一个简短的代码示例,这正是我想要做的

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

一切正常,但问题是,一旦消息框显示为“无响应错误”。请任何人帮助找出解决方案,您将需要使用.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()

您将需要使用.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()

线程和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
时),线程仍会继续运行!因此,如果你试图实现一些简单的事情,这是一个选择(快速和小的选择)

但是,如果您顽固地或真的需要创建(覆盖)线程对象的自定义子类,它将为您提供更大的灵活性来控制流

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()
    是一个不错的选择
  • 对于复杂和长时间执行的事情-
    线程化
    是您的选择
链接:

  • 此外,当事情变得复杂时:

线程和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
时),线程仍会继续运行!因此,如果你试图实现一些简单的事情,这是一个选择(快速和小的选择)

但是,如果您顽固地或真的需要创建(覆盖)线程对象的自定义子类,它将为您提供更大的灵活性来控制流

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()
    是一个不错的选择
  • 对于复杂和长时间执行的事情-
    线程化
    是您的选择
链接:

  • 此外,当事情变得复杂时:

这对我很有帮助