回答編集履歴

5

誤った情報のため修正

2021/04/23 16:02

投稿

teamikl
teamikl

スコア8760

test CHANGED
@@ -34,37 +34,35 @@
34
34
 
35
35
  ```python
36
36
 
37
+ # 事前にバックエンドを設定
37
38
 
39
+ import matplotlib
38
40
 
39
- def init_tk_window(root):
41
+ matplotlib.use('TkAgg')
40
-
41
- timer.stop()
42
42
 
43
43
 
44
44
 
45
- window = tk.Toplevel(root)
45
+ # root = tk.Tk() は figure 内で行われているので、キャンバス経由で参照
46
46
 
47
- window.title("tk window")
47
+ root = fig.canvas.get_tk_widget().master
48
-
49
- tk.Label(window, text="test").pack()
50
-
51
- tk.Button(window, text="Close this window", command=window.destroy).pack()
52
-
53
- tk.Button(window, text="Close this app", command=root.destroy).pack()
54
48
 
55
49
 
56
50
 
57
- timer = fig.canvas.new_timer(interval=100)
51
+ window = tk.Toplevel(root)
58
52
 
59
- timer.add_callback(init_tk_window, fig.canvas.get_tk_widget().master)
53
+ window.title("tk window")
60
54
 
61
- timer.start()
55
+ tk.Label(window, text="test").pack()
56
+
57
+ tk.Button(window, text="Close this window", command=window.destroy).pack()
58
+
59
+ tk.Button(window, text="Close this app", command=root.destroy).pack()
62
60
 
63
61
 
64
62
 
65
63
 
66
64
 
67
- # この後に plt.show() を呼び出し
65
+ # この後に plt.show() を呼び出し ... 内部で mainloop() が呼ばれる
68
66
 
69
67
  ```
70
68
 
@@ -78,7 +76,7 @@
78
76
 
79
77
 
80
78
 
81
- plt.show() 内部で tk.Tk() が呼び出される為、
79
+ ~~plt.show() 内部で tk.Tk() が呼び出される為、~~ 訂正: figure 生成時でした
82
80
 
83
81
  2重に初期化が行われてしまいます。
84
82
 
@@ -90,9 +88,9 @@
90
88
 
91
89
 
92
90
 
93
- plt.show() 内部で呼び出されるタイマーイベントで、
91
+ ~~plt.show() 内部で呼び出されるタイマーイベントで、~~
94
92
 
95
- tkinter のウィンドウを作るという回避策を取ります。
93
+ ~~tkinter のウィンドウを作るという回避策を取ります。~~
96
94
 
97
95
 
98
96
 
@@ -102,65 +100,7 @@
102
100
 
103
101
 
104
102
 
105
- ----
106
-
107
- 追記: 別解の紹介のみ、
103
+ 追記: コードを変更
108
-
109
-
110
-
111
- > root = tk.Tk() と plt.show() を同時に使うのはお勧めしません。
112
-
113
-
114
-
115
- 自己レスで、お勧めしないというスタンスは変わりないのですが、
116
-
117
- 理由: ライブラリの設計の都合により引きおこる問題があり、注意事項が増える為。
118
-
119
-
120
-
121
- ```python
122
-
123
- import matplotlib
124
-
125
- matplotlib.use('TkAgg') # <--- plt.show() 内で tkinter の mainloopが呼ばれるようになる
126
-
127
- from matplotlib import pyplot as plt
128
-
129
-
130
-
131
- import tkinter as tk
132
-
133
- tk.NoDefaultRoot() # <--- 初期化が重複した際に起こる問題の防止策
134
-
135
-
136
-
137
- root = tk.Tk()
138
-
139
- root.title("AAA")
140
-
141
- root.geometry("300x400")
142
-
143
-
144
-
145
- # 重要: NoDefaultRoot を使う場合の注意点。必ず親を指定する
146
-
147
- # e.g. NG: tk.StringVar() -> OK: tk.StringVar(master=root) 等、
148
-
149
-
150
-
151
- tk.Button(root, text="OK", command=root.destroy).pack()
152
-
153
-
154
-
155
- # root.mainloop() は自分では直接呼び出さない。
156
-
157
- # この後に plt.show() を呼び出し
158
-
159
- ```
160
-
161
-
162
-
163
- 上の方法より呼び出し部分の記述が少なくなるだけで、注意事項・制限は増えます。
164
104
 
165
105
 
166
106
 

4

追記

2021/04/23 16:02

投稿

teamikl
teamikl

スコア8760

test CHANGED
@@ -100,7 +100,69 @@
100
100
 
101
101
  ここは他により良い呼び出し方があるかもしれません)
102
102
 
103
+
104
+
103
-
105
+ ----
106
+
107
+ 追記: 別解の紹介のみ、
108
+
109
+
110
+
111
+ > root = tk.Tk() と plt.show() を同時に使うのはお勧めしません。
112
+
113
+
114
+
115
+ 自己レスで、お勧めしないというスタンスは変わりないのですが、
116
+
117
+ 理由: ライブラリの設計の都合により引きおこる問題があり、注意事項が増える為。
118
+
119
+
120
+
121
+ ```python
122
+
123
+ import matplotlib
124
+
125
+ matplotlib.use('TkAgg') # <--- plt.show() 内で tkinter の mainloopが呼ばれるようになる
126
+
127
+ from matplotlib import pyplot as plt
128
+
129
+
130
+
131
+ import tkinter as tk
132
+
133
+ tk.NoDefaultRoot() # <--- 初期化が重複した際に起こる問題の防止策
134
+
135
+
136
+
137
+ root = tk.Tk()
138
+
139
+ root.title("AAA")
140
+
141
+ root.geometry("300x400")
142
+
143
+
144
+
145
+ # 重要: NoDefaultRoot を使う場合の注意点。必ず親を指定する
146
+
147
+ # e.g. NG: tk.StringVar() -> OK: tk.StringVar(master=root) 等、
148
+
149
+
150
+
151
+ tk.Button(root, text="OK", command=root.destroy).pack()
152
+
153
+
154
+
155
+ # root.mainloop() は自分では直接呼び出さない。
156
+
157
+ # この後に plt.show() を呼び出し
158
+
159
+ ```
160
+
161
+
162
+
163
+ 上の方法より呼び出し部分の記述が少なくなるだけで、注意事項・制限は増えます。
164
+
165
+
104
166
 
105
167
 
106
168
 

3

語句の修正

2021/04/23 06:37

投稿

teamikl
teamikl

スコア8760

test CHANGED
@@ -1,10 +1,10 @@
1
1
  問題点:
2
2
 
3
- - tkinter の初期化が2度行われる
3
+ - tkinter の初期化の重複
4
4
 
5
5
   root = tk.Tk(), plt.show() 内部でも初期化される
6
6
 
7
- - イベントループの重複
7
+ - イベントループの競合
8
8
 
9
9
   root.mainloop(), plt.show() どちらもイベント待機するループ。
10
10
 

2

コード修正

2021/04/23 03:32

投稿

teamikl
teamikl

スコア8760

test CHANGED
@@ -26,7 +26,7 @@
26
26
 
27
27
 
28
28
 
29
- matplotlib のバックエンド tkagg にして、
29
+ matplotlib のバックエンド tkagg にして、
30
30
 
31
31
  tkinterの新しいウィンドウを作るのは Toplevel を使ってみてください。
32
32
 

1

コード修正

2021/04/22 17:03

投稿

teamikl
teamikl

スコア8760

test CHANGED
@@ -36,7 +36,7 @@
36
36
 
37
37
 
38
38
 
39
- def sub_tk_window(root):
39
+ def init_tk_window(root):
40
40
 
41
41
  timer.stop()
42
42
 
@@ -56,7 +56,7 @@
56
56
 
57
57
  timer = fig.canvas.new_timer(interval=100)
58
58
 
59
- timer.add_callback(sub_tk_window, fig.canvas.get_tk_widget().master)
59
+ timer.add_callback(init_tk_window, fig.canvas.get_tk_widget().master)
60
60
 
61
61
  timer.start()
62
62