teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

3

コード変更に伴い回答内の文章も修正

2021/05/11 07:49

投稿

teamikl
teamikl

スコア8817

answer CHANGED
@@ -8,10 +8,13 @@
8
8
 
9
9
 
10
10
  キャンバスのサイズを得るには、`canvas["width"]` や `cavas.winfo_reqwidth()` を用います。
11
- mainloop が始まる前では、キャンバスのサイズは 1 になっています。
11
+ ~~mainloop が始まる前では、キャンバスのサイズは 1 になっています。
12
- (その為 update() で更新してるのだと思いますが、不十分なケースが有るので)
12
+ (その為 update() で更新してるのだと思いますが、不十分なケースが有るので)~~
13
13
 
14
+ 追記: winfo_width() でサイズを正常に取れないケースを再現するコードを掲載してましたが、
15
+ 質問のコードに合わせて、ここは修正しました。
14
16
 
17
+
15
18
  coords() の戻り値は、0.0 .. 1.0 の値で表現されるので、ピクセルで座標を計算するには
16
19
  キャンバスのサイズを掛ける必要があります。
17
20
 
@@ -23,7 +26,9 @@
23
26
  解決策(どれかひとつ)
24
27
  - `create_text(canvas["width"]//2, canvas["height"]//2, ...)`
25
28
  - `create_text(canvas.winfo_reqwidth()//2, winfo_reqheight()//2, ...)`
26
- - キャンバス内容の初期化処理をタイマーから呼び出す。
29
+ - ~~キャンバス内容の初期化処理をタイマーから呼び出す。~~
30
+  追記: できれば mainloop 後に初期化したほうが良いのですが、
31
+  今回の問題には直接該当せず。
27
32
 
28
33
  検証用コード
29
34
  ```python

2

コード修正 winfo_width() で正常に値を取れないケースを再現するコードでしたが、canvas.update() のタイミングを質問のコードと同じになるように修正。

2021/05/11 07:49

投稿

teamikl
teamikl

スコア8817

answer CHANGED
@@ -49,6 +49,7 @@
49
49
 
50
50
  root = tk.Tk()
51
51
  canvas = tk.Canvas(root, width=400, height=400)
52
+ canvas.pack(fill=tk.BOTH, expand=True)
52
53
 
53
54
  ## mainloop 前に呼び出す(現状のコードに該当)
54
55
  # canvas.update()
@@ -63,7 +64,6 @@
63
64
  ## canvas.winfo_width を使う場合は、この様な呼び出しに
64
65
  # root.after(1, root.after_idle, init_canvas, "after 1 idle", canvas)
65
66
 
66
- canvas.pack(fill=tk.BOTH, expand=True)
67
67
  root.mainloop()
68
68
 
69
69
  ```

1

書きかけだった文章の補完

2021/05/11 07:46

投稿

teamikl
teamikl

スコア8817

answer CHANGED
@@ -72,15 +72,24 @@
72
72
  > カメラの接続が物理的に切れた場合などの処理をどうすればいいかわからない
73
73
 
74
74
  物理的に切れた時の挙動は デバイス固有またはOS によっても異なると思いますが、
75
+ 障害を検知した場合は、速やかにリソースを開放して、
76
+ エラーメッセージを表示といった対応をすることになると思います。
75
77
 
76
- 障害を検知した場合は、リソースを開放して、エラーメッセージを表示。
77
78
 
79
+ 切断時にGUIが一時的にフリーズする場合は、
80
+ 原因はイベントループ内での時間のかかるブロッキング処理なので、
81
+ 該当する処理(カメラからの読み込み)を別スレッドへ移すことで回避できます。
82
+ キャンバスへの描画はメインスレッド側で行う必要があるため、Queueで通信。
78
83
 
84
+ ※ 内蔵カメラでは発生しないかもしれません。
79
85
 
80
- vcap.read() ... 切断時はブロッキングする可能性があるので、回避するには スレッドを使う、timeout の設定等
81
86
 
87
+ 切断時にOSが落ちる場合は、
82
- デバイス固有の問題、デバイスドライバーの不具合等には、アプリケーション側では対応不可能です。
88
+ デバイス固有の問題、デバイスドライバーの不具合等には、
89
+ アプリケーション側では対応は難しいです。
83
90
 
91
+ (カメラではありませんが、古いusb接続のオーディオインターフェースで経験しました。)
92
+
84
93
  ----
85
94
  別問題ですが
86
95
  self.canvas.create_image ... 毎回 create_image はメモリリークになるので