赞
踩
Python使用tk编写GUI界面中Button调用方法如果执行时间过长(比如绑定的函数中有while循环)会导致
实测完美解决方法:
import threading
import time
def thread_it(fc):
t = threading.Thread(target=fc)
t.setDaemon(True)
t.start()
def target_fc():
time.sleep(10)
# 下面这句并不能直接使用,因为例子中我并没有引入import tkinter,仅表示示例
# Button绑定事件,如果有传递参数要通过lamda:+函数
button1 = ttk.Button(root, text='Button', command=lambda: thread_it(target_fc))
使用ctypes强行杀掉线程,下述例子仅表示如何关闭,开启的例子参考上面,代码并非直接升版,就比如下面例子中t
是假设已经开启的情况下
import inspect
import ctypes
def _async_raise(tid, exctype):
"""raises the exception, performs cleanup if needed"""
tid = ctypes.c_long(tid)
if not inspect.isclass(exctype):
exctype = type(exctype)
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
if res == 0:
raise ValueError("invalid thread id")
elif res != 1:
# """if it returns a number greater than one, you're in trouble,
# and you should call it again with exc=NULL to revert the effect"""
ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
raise SystemError("PyThreadState_SetAsyncExc failed")
def stop_thread(thread):
_async_raise(thread.ident, SystemExit)
# 假设开启了一个t线程,用下述方法可以直接关掉
stop_thread(t)
线程部分的代码在类中实现, 以下是部分代码,仅供参考
class App:
# 开启线程
def thread_it(self, fc):
self.t = threading.Thread(target=fc)
self.t.setDaemon(True)
self.t.start()
# 终止线程
def _async_raise(self, tid, exctype):
"""raises the exception, performs cleanup if needed"""
tid = ctypes.c_long(tid)
if not inspect.isclass(exctype):
exctype = type(exctype)
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
if res == 0:
raise ValueError("invalid thread id")
elif res != 1:
# """if it returns a number greater than one, you're in trouble,
# and you should call it again with exc=NULL to revert the effect"""
ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
raise SystemError("PyThreadState_SetAsyncExc failed")
def stop_thread(self, thread):
self._async_raise(thread.ident, SystemExit)
# 动态改变按钮状态,新增该函数是为避免绑定事件后,无法关闭线程而设立。
def change_button_runorstop(self):
# self.button.configure(text='取消执行') #动态更改button的文本显示
if self.button4["text"] == "执行":
self.thread_it(self.move_mouse_to)
elif self.button4["text"] == "取消执行":
self.button4["text"] = "执行"
self.stop_thread(self.t)
self.text_1.insert('1.0', '取消任务成功\n')
# 移动鼠标到指定位置
def move_mouse_to(self):
# 此处方法省略
def setup_widgets(self):
# 按钮绑事件
self.button4 = ttk.Button(self.tab_1, text="执行",command=self.change_button_runorstop) # command= lambda :self.thread_it(self.move_mouse_to))
self.button4.grid(row=1, column=4, padx=5, pady=10, sticky="nsew", rowspan=2)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。