@mickey1129

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

python threadingを利用してグラフを表示すると1回目の実行ではエラーが出ないが2回目以降の実行ではエラーが出る

解決したいこと

pythonでcsvデータ全体をグラフ表示したまま部分データのグラフを表示しようとしています。threadingを利用して全体グラフを表示する事で全体グラフと部分グラフを同時に表示できるようになりました。jupyter notebookを使用して実行しています。1回目の実行ではエラーが出ないのですが、2回目以降の実行ではエラーが出てしまいます。"Kernel"-"Restart"とすると再びエラーが出なくなるのですが、やはり2回目以降の実行ではエラーが出ます。1回目の実行と2回目以降の実行でエラーの有無が違っています。2回目以降でもエラーが出ないようにするにはどう修正すればよいかご教示頂けないでしょうか。
pythonを使い始めた初心者なので、その他にもコードの書き方等ご指導を頂けると幸甚です。

発生している問題・エラー

Exception ignored in: <function Image.__del__ at 0x000001EE6FDAA830>
Traceback (most recent call last):
  File "C:\Users\***\AppData\Local\Programs\Python\Python310\lib\tkinter\__init__.py", line 4046, in __del__
RuntimeError: main thread is not in main loop

該当するソースコード

import tkinter as tk
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import threading

def main():
    RC = ReadCSV()
    datCSV, datNum = RC.set_data()

    tra = PlotDatThread(datCSV, 0, datNum)
    tra.start()

    partNum = int(datNum/3)
    for i in range(3):
        PD = PlotDat(datCSV, partNum * i + 1, partNum * (i + 1))
        PD.plot()

    tra.join()

class ReadCSV:
# 実際はCSVデータの読込み
# 検討用データを入力する
    def __init__(self):
        self.datCSV = []

    def set_data(self):
        self.datCSV = [(0.000, 1.000), (0.007,-0.468), (0.013,-0.438), \
            (0.020, 0.819), (0.027,-0.383), (0.033,-0.358), (0.040, 0.670), \
            (0.047,-0.314), (0.053,-0.293), (0.060, 0.549), (0.067,-0.257), \
            (0.073,-0.240), (0.080, 0.449), (0.087,-0.210), (0.093,-0.197), \
            (0.100, 0.368), (0.107,-0.172), (0.113,-0.160), (0.120, 0.301), \
            (0.127,-0.141), (0.133,-0.132), (0.140, 0.247), (0.147,-0.115), \
            (0.153,-0.108), (0.160, 0.202), (0.167,-0.094), (0.173,-0.088), \
            (0.180, 0.165), (0.187,-0.077), (0.193,-0.072), (0.200, 0.135)]
        self.datCSV = tuple(self.datCSV)
        self.datNum = 31
        return self.datCSV, self.datNum

class PlotDatThread(threading.Thread):
    def __init__(self, dat, Psta, Psto):
        super().__init__()
        self.dat    = dat
        self.Pstart = Psta
        self.Pstop  = Psto

    def run(self):
        PA = PlotDat(self.dat, self.Pstart, self.Pstop)
        PA.plot()

class PlotDat():
# グラフを表示
    def __init__(self, dat, Psta, Psto):
        self.dat    = dat
        self.Pstart = Psta
        self.Pstop  = Psto
        self.plot_x = []
        self.plot_y = []

    def setData(self):
        for i in range(self.Pstart, self.Pstop):
            self.plot_x.append(self.dat[i][0])
            self.plot_y.append(self.dat[i][1])
        
    def plot(self):
        self.setData()

        self.fig, self.ax = plt.subplots()
        self.ax.plot(self.plot_x, self.plot_y)

        self.win = tk.Tk()
        if self.Pstart == 0:
            self.win.geometry("400x250+20+20")
            self.win.title("データ全体")
        else:
            self.win.geometry("400x250+430+20")
            self.win.title("部分表示")
        self.win.withdraw()
        self.win.protocol('WM_DELETE_WINDOW', lambda: self.destWin(self.win))
    
        self.canvas = FigureCanvasTkAgg(self.fig, master=self.win)
        self.canvas.draw()
        self.canvas.get_tk_widget().pack()

        self.win.update()
        self.win.deiconify()
        self.win.mainloop()

    def destWin(self, win):
        self.win = win
        self.win.quit()
        self.win.destroy()

if __name__ == "__main__":
    main()
0 likes

No Answers yet.

Your answer might help someone💌