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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

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

Tkinter

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

Q&A

解決済

1回答

9133閲覧

Python tkinterでcanvas上に円を描画するプログラムを作りたいのですが…

flower

総合スコア29

Python 3.x

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

Tkinter

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

0グッド

0クリップ

投稿2016/07/17 08:06

###前提・実現したいこと
Pyhonで以下のようなプログラムを作成しています。

・キャンバス上に赤色に塗りつぶした円をひとつ描画する。
・赤色に塗りつぶした円の内部をクリックした場合、その円の色を緑色に変える。
・緑色に塗りつぶした円の内部をクリックした場合、その円の色を青色に変える。
・青色に塗りつぶした円の内部をクリックした場合、その円の色を赤色に変える。
・円の外側をクリックしても何もしない。

最初のクリックで赤色に塗りつぶした円を描画し、キャンバス上のどこかをクリックした際に、円の塗りつぶし色を変える、というところまでは作ることができたのですが、円の内部の範囲の指定がうまくいきません。

###発生している問題・エラーメッセージ
エラーメッセージ以前に問題が解けません。

###課題のヒントで与えられた疑似コード

クリックされたとき(イベント情報): IF クリックされた位置が円の外側: RETURN IF 現在の色が赤: 円を緑に塗りつぶす 現在の色を緑に設定する ELSE IF 現在の色が緑: 円を青に塗りつぶす 現在の色を青に設定する ELSE IF 現在の色が青: 円を赤に塗りつぶす 現在の色を赤に設定する

###試したこと

Python

1from tkinter import * 2 3tk = Tk() 4c = Canvas(tk, width = 400, height = 300) 5c.pack() 6 7color = "red" 8 9def on_click(event): 10 global color 11 x = event.x 12 y = event.y 13 c.create_oval(20, 20, 150, 150, fill = color) 14 if (x-20)*(x-20) + (y-20)*(y-20) > 150*150: 15 return 16 if color == "red": 17 c.create_oval(20, 20, 150, 150, fill = color) 18 color = "blue" 19 elif color == "blue": 20 c.create_oval(20, 20, 150, 150, fill = color) 21 color = "green" 22 elif color == "green": 23 c.create_oval(20, 20, 150, 150, fill = color) 24 color = "red" 25c.bind("<Button-1>",on_click) 26 27tk.mainloop()

↑このままだと円の外でクリックしても色を変えることができてしまうのです。

###補足情報(言語/FW/ツール等のバージョンなど)
使用ツール:Python3.5.1

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

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

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

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

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

guest

回答1

0

ベストアンサー

クリックした座標を変換する計算は、- 20だけでは足りません。

座標が円の中かどうかを計算するには、
まずマウスイベントの座標をグラフ上の座標に補正する必要がありますが、
円の中心が(0, 0)となるように座標を補正する計算は、
「マウスクリックした座標 - 円の半径 - 左上の座標」
にしなければなりません。
つまり、「円の半径」が足りません。

参考:create_ovalの第1引数、第2引数は、円に外接する長方形の左上の座標、第3引数、第4引数は、円の幅・高さではなく、同じく外接する長方形の右下の座標を指定します。

最終的には下記のようにすれば良いです。

他のところも少し変えてしまいました。
ちょっと中途半端に変えてしまっていますので、他にも例えば同じ値が複数出てきているところは、変数に置き換えたほうが良いでしょう。

lang

1from tkinter import * 2 3tk = Tk() 4c = Canvas(tk, width = 400, height = 300) 5c.pack() 6 7d = 150 - 20 # 直径 8r = d / 2.0 # 半径 9rr = r * r # 半径^2 10cx = 20 # 円の左上X 11cy = 20 # 円の左上Y 12ax = cx + r # X=0の位置 13ay = cy + r # Y=0の位置 14 15color = "red" 16c.create_oval(20, 20, 150, 150, fill = color) 17 18def on_click(event): 19 global color 20 x = event.x 21 y = event.y 22 23 dx = x - ax # グラフ上の座標X 24 dy = y - ay # グラフ上の座標Y 25 26 if dx * dx + dy * dy > rr: 27 return 28 if color == "red": 29 color = "blue" 30 elif color == "blue": 31 color = "green" 32 elif color == "green": 33 color = "red" 34 c.create_oval(20, 20, 150, 150, fill = color) 35c.bind("<Button-1>",on_click) 36 37tk.mainloop()

投稿2016/07/17 11:32

編集2016/07/17 11:47
argius

総合スコア9390

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

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

flower

2016/07/17 12:54

なるほど…まずcreate_ovalの第1引数、第2引数が何を示すかなどもよくわかっていなかったので、とても納得いきました。丁寧なご説明をありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問