tkinter以多线程方式用matplot绘图崩溃问题

tkinter中以多线程方式用matplotlib绘图出现程序崩溃问题

  • 需求:需要绘制一幅动态图(大约3000帧左右)。但是数据量太大,约莫绘制到60-200帧不等时,出现程序未响应。

  • 解决:开启线程去解决这个需求

  • 问题:当使用线程,并用matplotlib画图之后,绘制到tkinter窗体上,出现程序直接崩溃

一个以多线程方式用plt绘图到tkinter上程序崩溃的小demo

import tkinter as tk
import threading  # 导入多线程模块


class GUI:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title('演示窗口')
        self.root.geometry("1024x960+1100+150")
        self.interface()

    def interface(self):
        """"界面编写位置"""
        self.Button0 = tk.Button(self.root, text="确定", command=self.start)
        self.Button0.grid(row=0, column=0)

        self.w1 = tk.Text(self.root, width=80, height=10)
        self.w1.grid(row=1, column=0)



    def event(self):
        '''按钮事件,一直循环'''
        a = 0
        while True:
            a += 1
            self.w1.insert(1.0, str(a) + '\n')
            self.figure = Figure(figsize=(5, 5), dpi=100)
            self.subplot = self.figure.add_subplot(1, 1, 1)
            self.subplot.set(xlim=[0, 20], ylim=[0, 20])
            # self.subplot.xaxis.set_ticks(np.arange(0, 26, 1))
            self.canvas = tk.Canvas(self.root,bg="red")
            self.canvas_fig = FigureCanvasTkAgg(self.figure, master=self.canvas)
            # 3.2 将这个中间件放到图像绘制
            self.subplot.plot(np.array(range(10)))
            self.canvas_fig.draw()
            self.canvas.place(relx=0.2, rely=0.2, relwidth=0.8, relheight=0.8)
            break


    def start(self):
        self.T = threading.Thread(target=self.event)  # 多线程
        self.T.setDaemon(True)  # 线程守护,即主进程结束后,此线程也结束。否则主进程结束子进程不结束
        self.T.start()  # 启动


if __name__ == '__main__':
    a = GUI()
    a.root.mainloop()
  • 运行示例:

    根据代码,点击确定会以线程方式在白框位置输出信息,同时在窗体的右下角出现一幅图像。

  • 点击确定按钮之后

  • 白框位置出现输入之后,过一会还未出现绘图,程序直接闪退

  • 经过测试,发现问题出现在self.canvas_fig.draw()。每当运行到此处时,程序崩溃

  • 解决程序崩溃方案:执行draw()方法时,用after()方式。如:self.root.after(100, self.canvas_fig.draw)

  • 改动后的demo代码

    import tkinter as tk
    import threading  # 导入多线程模块
    
    
    class GUI:
        def __init__(self):
            self.root = tk.Tk()
            self.root.title('演示窗口')
            self.root.geometry("1024x960+1100+150")
            self.interface()
    
        def interface(self):
            """"界面编写位置"""
            self.Button0 = tk.Button(self.root, text="确定", command=self.start)
            self.Button0.grid(row=0, column=0)
    
            self.w1 = tk.Text(self.root, width=80, height=10)
            self.w1.grid(row=1, column=0)
    
    
    
        def event(self):
            '''按钮事件,一直循环'''
            a = 0
            while True:
                a += 1
                self.w1.insert(1.0, str(a) + '\n')
                self.figure = Figure(figsize=(5, 5), dpi=100)
                self.subplot = self.figure.add_subplot(1, 1, 1)
                self.subplot.set(xlim=[0, 20], ylim=[0, 20])
                # self.subplot.xaxis.set_ticks(np.arange(0, 26, 1))
                self.canvas = tk.Canvas(self.root,bg="red")
                self.canvas_fig = FigureCanvasTkAgg(self.figure, master=self.canvas)
                # 3.2 将这个中间件放到图像绘制
                self.subplot.plot(np.array(range(10)))
                self.root.after(100, self.canvas_fig.draw)
                # self.canvas_fig.draw()
                self.canvas.place(relx=0.2, rely=0.2, relwidth=0.8, relheight=0.8)
                break
    
    
        def start(self):
            self.T = threading.Thread(target=self.event)  # 多线程
            self.T.setDaemon(True)  # 线程守护,即主进程结束后,此线程也结束。否则主进程结束子进程不结束
            self.T.start()  # 启动
    
    
    if __name__ == '__main__':
        a = GUI()
        a.root.mainloop()
    
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值