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

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

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

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

Python 3.x

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

Tkinter

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

Q&A

解決済

1回答

1931閲覧

python TKinterへの組み込みが上手くいかず更新に失敗する

TheBullchannel

総合スコア33

Matplotlib

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

Python 3.x

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

Tkinter

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

0グッド

0クリップ

投稿2020/10/11 15:01

mplfinanceで作成したチャートをTKinterに組み込もうとしておりますが上手くいきません。
コードを入力するとchart()が呼び出され、チャートが作成される様に書いたつもりなのですが、コード入力2回目以降でチャートの更新が失敗しチャートが削除されずに下へ移動してしまいます。
入力2回目以降でチャート作成前にfigを消す為にfig.clf()を記述したところ、真っ白い画面が作成され、その下に以前作成したチャートが残ってしまいます。

どの様に記述すればよいのかご教示ください。
よろしくお願いします。

イメージ説明
イメージ説明

chartcount = 0 def chart(): global chartcount df = pd.read_csv('C:/python/temp/1301.csv', parse_dates=True) df.columns = ['Open', 'High', 'Low', 'Close', 'Volume'] mc = mpf.make_marketcolors( up='#ff6820',down='#3cb371', edge={'up':'#ff6820','down':'#3cb371'}, wick={'up':'#ff6820','down':'#3cb371'}, volume='tab:green' ) fig, axlist = mpf.plot(dff[-50:],figratio=(5.8,9),figscale=1,style=mpf.make_mpf_style(marketcolors=mc), returnfig=True,type='candle', volume=True,scale_width_adjustment=dict(volume=0.4,candle=1)) canvas = FigureCanvasTkAgg(fig, master=frame) if chartcount == 0: canvas.draw() canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH) chartcount += 1 else: fig.clf() canvas.draw() canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH) chartcount += 1

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

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

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

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

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

guest

回答1

0

ベストアンサー

コードを入力するとchart()が呼び出され、チャートが作成される様に書いたつもりなのですが、
コード入力2回目以降でチャートの更新が失敗しチャートが削除されずに下へ移動してしまいます。

chart() が複数回呼ばれているので、毎回チャートを表示するキャンバスを作成されてます。

白くなるのは、fig.clf() の為だと思います。
fig は毎回新規作成されてる為、「以前のチャートをクリア」にはなってません、
今回のチャートをクリアしてます。


問題を Label で再現したコード

python

1#!/usr/bin/env python3.8 2 3import tkinter as tk 4 5def main(): 6 count = 0 7 root = tk.Tk() 8 9 def click(): 10 nonlocal count 11 count += 1 12 label = tk.Label(root, text="Label {}".format(count)) # 毎回作られる 13 label.pack() 14 button = tk.Button(root, text="Click", command=click) 15 button.pack() 16 root.mainloop() 17 18if __name__ == '__main__': 19 main()

解決策1: ウィジェットは新規作成せずに、表示するデータのみを更新する。

python

1#!/usr/bin/env python3.8 2 3import tkinter as tk 4 5def main(): 6 count = 0 7 root = tk.Tk() 8 9 def update_label(): 10 nonlocal count 11 count += 1 12 label.config(text=f"Label {count}") 13 button = tk.Button(root, text="Label {}".format(count), command=update_label) 14 button.pack() 15 label = tk.Label(root) 16 label.pack() 17 update_label() 18 root.mainloop() 19 20if __name__ == '__main__': 21 main()

解決策2: 不要になった以前のウィジェットを事前に破棄する。

python

1#!/usr/bin/env python3.8 2 3import tkinter as tk 4 5def main(): 6 count = 0 7 label = None 8 root = tk.Tk() 9 10 def click(): 11 nonlocal count, label 12 count += 1 13 if label: 14 label.destroy() # ウィジェットを破棄する 15 label = tk.Label(root, text="Label {}".format(count)) 16 label.pack() 17 button = tk.Button(root, text="Click", command=click) 18 button.pack() 19 root.mainloop() 20 21if __name__ == '__main__': 22 main()

このLabel に相当するのが、canvas = FigureCanvasTkAgg(fig, master=frame) です。
キャンバス作成と配置(pack())を chart() 関数外で事前に一度のみ行うようにしてみてください。

投稿2020/10/11 18:00

teamikl

総合スコア8760

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

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

TheBullchannel

2020/10/12 22:53

ご回答ありがとうございます。 label.destroy()にならってcanvas.get_tk_widget().destroy() と入力したところ、 _tkinter.TclError: bad window path name ".!labelframe5.!canvas"とエラーが出てしまいます。 どうやら、destroy後の canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True) でエラーが出ているようなのですが、これはどの様に対処したらよいでしょうか。
teamikl

2020/10/12 23:15

_tkinter.TclError: bad window path name は、無効なウィジェット(破棄済みのモノ)に対しての操作です。 pack() を呼び出すのは、canvas生成直後に呼び出します。 destroy() を使うという事は、解決策2 を取ったのだと思いますが、 その場合は、canvas を新たに毎回作る必要があります。 1. (以前のキャンバスがあれば) destroy  ※ この場合、以前のキャンバスをローカル変数以外に保持する為   変数 canvas は関数の外側に置く必要があります。   (nonlocal と 外側のスコープで label = None してる点に留意) 2. canvas を新規作成 3. pack()
TheBullchannel

2020/10/13 05:29

何度も詳しく教えて下さりありがとうございました! canvas をグローバル変数とし、教えて頂いた通りに記述したところ、無事希望の動作となりました。 大変感謝いたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問