|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
用 matplotlib 配合 tkinter 做了一个数据实时曲线显示窗口,窗口关闭时弹出RuntimeError: main thread is not in main loop
程序里开启了线程thread1 用来重画曲线
关闭窗口时 ,主线程关闭,thread1 还在运行
我觉得是因为这个报错
该怎么解决啊?
代码如下
from tkinter import *
from tkinter import font
import time
from pylab import *
import matplotlib
import random
import matplotlib.pyplot as plt
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg,NavigationToolbar2TkAgg
from matplotlib.figure import Figure
import numpy as np
from threading import Thread
class jiemian(Tk):
'''
主窗口
'''
def __init__(self):
'''
初始化
'''
super().__init__()
self.wm_title('实时绘图测试')
self.stime = time.time()
self.ltime = time.time()
self.createWidgets()
def createWidgets(self):
'''
界面
'''
# 设置字体
self.ft1 = font.Font(family='微软雅黑', size=40, weight=font.BOLD)
self.ft2 = font.Font(family='微软雅黑', size=15, weight=font.BOLD)
self.ft3 = font.Font(family='微软雅黑', size=10, weight=font.BOLD)
self.ft4 = matplotlib.font_manager.FontProperties(fname = 'c:/Windows/Fonts/msyh.ttf')
self.float_mynumber = DoubleVar()
self.str_mynumber = StringVar()
self.float_number = 1.0
self.int_x = [0]
self.int_y1 = [0]
self.int_y2 = [0]
self.str_time = [0]
fig= Figure(figsize=(12,4), dpi=100)
self.ax = fig.add_subplot(111)
self.thelabel_tittle = Label(self, text="实时绘图测试",font=self.ft1)
self.thelabel_number = Label(self,textvariable = self.str_mynumber,relief=SUNKEN,state=ACTIVE,padx=20,pady=10, width = 10)
self.thelabel_time = Label(self, textvariable=self.str_mynumber, relief=SUNKEN, state=ACTIVE, padx=20,
pady=10, width=10)
self.canvas = FigureCanvasTkAgg(fig , master = self)
self.canvas.get_tk_widget().grid(row=10,columnspan=30,padx=100,pady=10)
self.canvas._tkcanvas.grid(row=10,columnspan=30,padx=100,pady=10)
#toolbar = NavigationToolbar2TkAgg(self.canvas, self).get_tk_widget().grid(row=30,columnspan=10,padx=100,pady=10)
#toolbar.get_tk_widget().grid(row=30,columnspan=10,padx=100,pady=10)
#toolbar.update()
#self.thecanvas_m = Canvas(self,width=400,height = 400)
self.thescale = Scale(self,orient = HORIZONTAL, length = 284, from_ =0, to = 250,tickinterval = 50,
variable = self.str_mynumber,)
self.thelabel_tittle.grid(row=0,columnspan=100,padx=100,pady=10)
self.thelabel_number.grid(row=5, columnspan=10, padx=100, pady=10)
#self.thecanvas_m.grid(row=10,columnspan=30,padx=100,pady=10)
self.thescale.grid(row=20, columnspan=100, padx=100, pady=10)
self.mythread = Thread(target=self.myrun, name='thread-1', daemon=True)
self.mythread.start()
self.mainloop()
def mydraw(self):
'''绘图逻辑'''
x = np.random.randint(0,50,size = 100)
y = np.random.randint(0,50,size = 100)
self.ax.clear()
if len(self.int_x) == len(self.int_y1) and len(self.int_x) == len(self.int_y2):
self.ax.plot(self.int_x,self.int_y1,linestyle = '-',color = 'r',label = u'数值')
self.ax.plot(self.int_x, self.int_y2, 'g--', label=u'数值')
#if len(self.int_x)>100:
#list_temp = [n for n in self.int_x[-100:] if n%5==0]
#self.ax.set_xticks([n for n in self.int_x[-100:] if n%5==0])
#self.ax.set_xticklabels(self.str_time)
locs,labels =plt.xticks()
plt.xticks(locs,self.str_time)
self.ax.set_xlabel('时间',fontproperties = self.ft4)
self.ax.legend(loc = 'best',prop = self.ft4)
self.canvas.show()
def myrun(self):
while 1 :
self.mydraw()
nowtime = time.time()
if (nowtime - self.ltime) >=1:
if len(self.int_x)>=100:
self.int_x = self.int_x[1:]
self.int_x.append(int(nowtime - self.stime))
self.str_time.append(time.strftime("%X",time.localtime()))
if len(self.int_y1) >= 100:
self.int_y1 = self.int_y1[1:]
self.int_y1.append(int(self.str_mynumber.get()))
if len(self.int_y2) >= 100:
self.int_y2 = self.int_y2[1:]
self.int_y2.append(random.randint((int(self.str_mynumber.get())-10),(int(self.str_mynumber.get())+10)))
self.ltime = nowtime
if __name__ == '__main__':
jinmian = jiemian()
报错信息:
Exception in thread thread-1:
Traceback (most recent call last):
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python35\lib\threading.py", line 914, in _bootstrap_inner
self.run()
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python35\lib\threading.py", line 862, in run
self._target(*self._args, **self._kwargs)
File "C:\Users\Administrator\Desktop\新建文本文档 (2).txt", line 93, in myrun
self.mydraw()
File "C:\Users\Administrator\Desktop\新建文本文档 (2).txt", line 90, in mydraw
self.canvas.show()
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python35\lib\site-packages\matplotlib\backends\backend_tkagg.py", line 356, in draw
self._master.update_idletasks()
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python35\lib\tkinter\__init__.py", line 1030, in update_idletasks
self.tk.call('update', 'idletasks')
_tkinter.TclError: can't invoke "update" command: application has been destroyed
运行环境
win7 python3.5
这样写只是掩盖了问题,并没有解决问题。
提供一种结束线程的方法吧~
- import threading
- import time
- cond= threading.Condition() # 条件锁
- isStoped=False
- def thd(cond):
- print('开始')
- n=0
- while 1:
- cond.acquire() # 锁
- n+=1
- print(n) # 要完成的事
- cond.wait(1) # 休眠 1秒
- if isStoped:break # 退出线程循环
- cond.release() # 解锁
-
- cond.release() # 解锁
- print('结束')
-
- #启动线程
- threading.Thread(target=thd,args=(cond,)).start()
- time.sleep(10) # 等10秒,让线程干事
- cond.acquire()
- isStoped=True # 设置结束标志
- cond.notify() # 唤醒休眠的线程,立即结束。
- cond.release()
复制代码
|
|