質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Matplotlib

MatplotlibはPythonのおよび、NumPy用のグラフ描画ライブラリです。多くの場合、IPythonと連携して使われます。

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1297閲覧

<tkinter>ボタンを押したとき最小二乗法の線の交点を求めたい

A_7

総合スコア4

Matplotlib

MatplotlibはPythonのおよび、NumPy用のグラフ描画ライブラリです。多くの場合、IPythonと連携して使われます。

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/11/19 09:06

編集2020/11/19 12:32

前提・実現したいこと

 tkinter上に読み込んだcsvファイルを表示させ、グラフ上で、マウスの右クリックで最小二乗法したい範囲を選択し、左ダブルクリックで最小二乗法の線を引く。これを二回行い、二本の最小二乗法の線を引いた後、tkinter上に表示される"交点"というボタンを押すと二本の最小二乗法の交点の部分に点を打つというプログラムを作成したいと考えております。
tkinter上にグラフを表示させ、マウス操作を行い、ボタンを設置するところはできたのですが、ボタンを押しても交点に点を打てず、下記のようなエラーメッセージが出ます。このエラーメッセージの解決方法がわからず、悩んでおります。

発生している問題・エラーメッセージ

can't invoke "update" command: application has been destroyed

該当のソースコード

python

1from tkinter import * 2from matplotlib import pyplot as plt 3from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg 4import numpy as np 5from scipy import optimize 6import pylab 7import turtle 8import tkinter as tk 9 10x_data = [] 11y_data = [] 12katamuki = [] 13seppen = [] 14state = 0 15f = open('xrr_data.csv', 'r') 16 17datalist = f.readlines() 18for data in datalist: 19 if state == 1: 20 x_data.append(float(data.split(',')[0])) 21 y_data.append(float(data.split(',')[1])) 22 if "Angle,Intensity" in data: 23 state =1 24 25f.close() 26xdata = np.array(x_data) 27ydata = np.array(y_data) 28 29 30def drawlsm(lind,rind): 31 32 global xdata2 33 global ydata2 34 35 xdata2 = xdata[lind:rind] 36 ydata2 = ydata[lind:rind] 37 38 parameter0 = [0.,0.] 39 result = optimize.leastsq(fit_func,parameter0,args=(xdata2,ydata2)) 40 print(result) 41 a_fit=result[0][0] 42 b_fit=result[0][1] 43 print(a_fit,b_fit) 44 plt.plot(xdata,a_fit*xdata+b_fit,'k-', label='fitted line', linewidth=3, alpha=0.3) 45 46 47#Least squares method with scipy.optimize 48def fit_func(parameter,x,y): 49 a = parameter[0] 50 b = parameter[1] 51 residual = y-(a*x+b) 52 return residual 53 54def oncmask(event): 55 56 global stat 57 global leftind, rightind 58 59 ind=np.searchsorted(xdata,event.xdata) 60 plt.title("You clicked index="+str(ind)) 61 if event.button==3 and stat==1: 62 leftind=ind 63 ax.plot([xdata[ind]],[ydata[ind]],".",color="red") 64 stat=2 65 elif event.button==3 and stat==2: 66 rightind=ind 67 ax.plot(xdata[leftind:rightind],ydata[leftind:rightind],color="red") 68 stat=3 69 print (leftind, rightind) 70 elif event.button==1 and event.dblclick==1 and stat==3: 71 plt.title("Approved") 72 mask[leftind:rightind]=False 73 drawlsm(leftind,rightind) 74 stat=1 75 elif event.button==2 and stat==3: 76 plt.title("Canceled") 77 ax.plot(xdata[leftind:rightind],ydata[leftind:rightind],color="blue") 78 ax.plot([xdata[leftind]],[ydata[leftind]],".",color="green") 79 stat=1 80 fig.canvas.draw() 81 82katamuki2 = np.array(katamuki) 83seppen2 = np.array(seppen) 84 85 86def getintersection():#一番最後とその1つ前に引いた線の交点をget 87 global xa #交点x座標 88 indent = len(katamuki2)#傾きリストの要素数 89 indent2= len(seppen2)#切片のリストの要素数 90 print("傾きリストの要素数={}, 切片リストの要素数={}".format(indent,indent2)) 91 #xa求める 92 xa=(seppen2[indent2-1]-seppen2[indent2-2])/(katamuki2[indent-2]-katamuki2[indent-1])#(b1-b0)/(a0-a1) 93 print("交点座標={}".format(xa)) 94 ya=katamuki2[indent-1]*xa+seppen2[indent2-1]#x座標からy座標を求める 95 plt.plot(xa,ya,".",color="m")#交点プロット 96 plt.show() 97 fig.canvas.draw() 98 99#x=np.arange(0, 10, 0.1) 100#y= np.random.rand(100) 101 102mask=np.ones(len(xdata),dtype=bool) 103 104stat = 1 105fig=plt.figure() 106ax=fig.add_subplot(111) 107ax.plot(xdata,ydata) 108 109# Windowの設定 110root = Tk() 111root.title("Plot window") 112root.geometry() 113 114# Frameの設定 115frame_1 = Frame(root, bd=4, relief=GROOVE) 116frame_2 = Frame(root, bd=4, relief=GROOVE) 117 118# widgetの設定 119btn2 = Button(frame_1,text='交点',font=("",18),command=getintersection) 120canvas = FigureCanvasTkAgg(fig, frame_2)#figをcanvasにのっける 121 122# widgetの配置 123frame_1.grid(row=0, column=0, sticky=W + E) 124frame_2.grid(row=1, column=0) 125btn2.pack(fill=X) 126canvas.get_tk_widget().grid(row=0, column=0) 127 128cid = fig.canvas.mpl_connect('button_press_event', oncmask) 129 130canvas.start_event_loop() 131

試したこと

ボタンを押したときにtkinterを終了するプログラムを作成して試してみたところ、tkinterの終了はできましたが同じエラーメッセージが出ました。

補足情報(FW/ツールのバージョンなど)

Python初心者で、説明不足や至らない点があると思いますが、アドバイス頂けたら嬉しいです。
よろしくお願いします。

"追記"
excelデータはこのようになっております。

列1列2
AngleIntensity
0.027879036
0.029838848
0.031766020
0.033745008
0.035714204
0.037695844
0.039677280
0.041656268
0.043628116
0.045661164
0.047649332
0.049651984
0.051640560
0.053631788
0.055647496
0.057643620
0.059656064
0.061641988
0.063668916
0.065663000
0.067671160
0.069661164
0.071680136
0.073666876
0.075691560
0.077681564
0.079712368
0.081706656
0.083744600
0.085720732
0.087740520
0.089750108
0.091745008
0.093754800
0.095776832
0.097777240
0.099778260
0.101778260
0.103795396
0.105810492
0.107812124
0.109813960
0.111812532
0.113807636
0.115838440

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

teamikl

2020/11/19 10:05

コードの実行に必要な最低限のデータで良いので csv データの掲載をお願いします。 もしくは、テスト用に問題のエラーの再現が出来るデータを、 スクリプト内に埋め込んでコードを掲載して頂けると、 環境構築の手間が省けるので助かります。 実行はしてませんが、tkinter を一緒に使う場合は、 plt.show() の併用が問題が起こりそうなポイントです。 確認: エラーが出るのは「交点」のボタンから呼ばれる、 getintersection関数内ですか?エラーログに行数等は表示されてませんか?
A_7

2020/11/19 12:40

ご指摘ありがとうございます。説明不足で申し訳ありません。 excelデータを質問の方に表で追記しました。目を通して頂けたら幸いです。 「交点」のボタンのgetintersection関数だけで実行してみたのですが、このようなエラーメッセージは出てきませんでした。 エラーメッセージの前にこのような表示がありました。 File "C:ファイル名", line 1305, in update self.tk.call('update') TclError: can't invoke "update" command: application has been destroyed
teamikl

2020/11/19 15:20

ボタンを押したときには同様のエラーを再現できませんでした。 エラーの再現に、他に必要な操作はありますか?(グラフをクリックしてから交点?) TypeError や IndexError がでます。(画面の枠外をクリックした時・交点ボタンをクリックした時) また、ウィンドウを閉じてプログラムを終了したときに 「交点」のボタンを押していなくても 上記のTclError が起こります。 恐らく、3つくらいの問題があって、 報告されてるエラーは別の問題のもののようです。 終了時の問題については心当たりがあるので回答します。
A_7

2020/11/20 05:46

TclErrorはボタンを押したときに起こるのではなく、tkinterのウィンドウを閉じた時に起こるものでした。 「交点」ボタンを押したときにはteamikl様の仰る通りIndexErrorが発生してしまいます。 Error動作の誤解や説明不足でお手数をお掛けしてしまい、申し訳ございません。 TclErrorについての回答をして頂き、本当にありがとうございます。
guest

回答1

0

ベストアンサー

プログラム終了時の問題について

(※追記: 交点の問題に対する回答ではありません)

原因: 破棄(destroy)されたウィジェットに対して、
稼働中のイベントループがアクセスしようとしています。

対策: tkinter/matplotlib を合わせて使う場合は、
予めイベントループを止めてから destroy するようにします。

python

1def _quit(): # 全てのウィンドウが閉じられた時に呼び出される 2 canvas.stop_event_loop() 3 root.destroy() 4root.protocol("WM_DELETE_WINDOW", _quit)

因みに、canvas.start_event_loop ではなく root.mainloop を使う場合は、
canvas.stop_event_loop の代わりに root.quit と、
イベントループに対応した停止メソッドを使います。


通常の tkinter のプログラムでは、
ウィンドウを閉じるとプログラムの終了なので、
これらのメソッドはどちらもプログラムの終了として扱われる事が多いのですが、
イベントループが絡む場合使い分けが必要になることも有ります。

  • root.destroy リソースの破棄
  • root.quit イベントループの停止

投稿2020/11/19 15:28

編集2020/11/19 15:29
teamikl

総合スコア8664

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

A_7

2020/11/20 05:50

回答をして頂き、ありがとうございます。 無事にTclErrorを解決する事ができました。 tkinterとmatplotlibを合わせて使用する時のイベントループの止め方がわからなかったので非常に勉強になりました。 本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問