「グローバル名 'x1' が定義されていません」問題の解決
デバッグ時の経験則としては、エラー メッセージが真実を伝えていると想定することです。この場合、「x1」という名前のグローバル変数がないということです。だから「なぜ?」と自分に問いかけてみてください。「x1」変数をまったく作成していないか、グローバルではない方法で作成しています。
あなたの場合、x1、y1、x2、および y2 を定義すると、それらをローカル変数として作成します。これは、変数を作成するときの Python のデフォルトの動作です。最も簡単な解決策は、それらをグローバルとして宣言することです。
def xaxis(event):
global x1, y1
x1, y1 = (event.x - 1), (event.y - 1)
def yaxis(event):
global x2, y2
x2, y2 = (event.x + 1), (event.y + 1)
無関係な 2 つ目の問題
バインディングの方法に関して、コードに別の問題があります。次のコード スニペットを検討してください。
w.bind("<ButtonRelease-1>", yaxis)
w.bind("<ButtonRelease-1>", create)
2 つのバインドを作成するのではなく、1 つを作成してから、別のバインドで上書きします。ただし、2 つのバインディングは必要ありません。create 関数内から yaxis 関数を呼び出すことができます。
オブジェクト指向アプローチの使用
ただし、グローバル変数は通常、問題に対する最善の解決策ではありません。オブジェクト指向アプローチの使用に切り替えた場合は、座標をオブジェクトの属性として保存できます。完全な実際の例を次に示します。
import Tkinter as tk
class ExampleApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.x = self.y = 0
self.canvas = tk.Canvas(self, width=400, height=400, cursor="cross")
self.canvas.pack(side="top", fill="both", expand=True)
self.canvas.bind("<ButtonPress-1>", self.on_button_press)
self.canvas.bind("<ButtonRelease-1>", self.on_button_release)
def on_button_press(self, event):
self.x = event.x
self.y = event.y
def on_button_release(self, event):
x0,y0 = (self.x, self.y)
x1,y1 = (event.x, event.y)
self.canvas.create_rectangle(x0,y0,x1,y1, fill="black")
if __name__ == "__main__":
app = ExampleApp()
app.mainloop()
マウスをドラッグしながら描く
カーソルをドラッグしながら四角形を描きたい場合は、プログラムを変更して、ボタンを押したときに四角形を作成することができます。オブジェクトに一意のタグを付けるか、キャンバスIDを保存すると、キャンバス オブジェクトのcoordsメソッドを使用して現在の四角形の座標を調整するマウス モーション イベントを設定できます。聞かれた質問とは直接関係ないので、読者の演習として残しておきます。