1
def xaxis(event):
   x1, y1 = (event.x - 1), (event.y - 1)

def yaxis(event):
   x2, y2 = (event.x + 1), (event.y + 1)

def create(event):
   w.create_rectangle(x1,y1,x2,y2,fill='Black')

w = Canvas(root, width=canvas_width, height=canvas_height)
w.config(cursor='cross')
w.pack(expand=YES, fill=BOTH)
w.bind("<Button-1>", xaxis)
w.bind("<ButtonRelease-1>", yaxis)
w.bind("<ButtonRelease-1>", create)

シェルは言う

Tkinter コールバック トレースバックの例外 (最新の呼び出しが最後):
ファイル "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py"、行 1410、呼び出しで return self。 func(*args) ファイル "/Users/Leo/Desktop/draw.py"、22 行目、create w.create_rectangle(x1,y1,x2,y2,fill='Black') NameError: グローバル名 'x1' は定義されていません

そして、作成機能は他の機能の座標を取得できないと思います...

あとで座標が必要なのでこうしました!

あなたが私を助けてくれることを願っています.. ;-)ありがとう!

4

3 に答える 3

9

「グローバル名 '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メソッドを使用して現在の四角形の座標を調整するマウス モーション イベントを設定できます。聞かれた質問とは直接関係ないので、読者の演習として残しておきます。

于 2012-10-11T10:57:56.553 に答える
1

x1etc. をそれぞれの関数 (例 ) でローカルに設定しただけなxaxisので、 では使用できませんcreate。これらを書き換えて、目的の結果を返すことができます。

def xaxis(event):
   return (event.x - 1), (event.y - 1) # x1, y1

def yaxis(event):
   return (event.x + 1), (event.y + 1) # x2, y2

def create(event):
   x1, y1 = xaxis(event)
   x2, y2 = yaxis(event)
   w.create_rectangle(x1,y1,x2,y2,fill='Black')
于 2012-10-11T10:35:39.363 に答える
0

x1、x2...の結果をローカル変数に保存しています。これらの値は、イベントハンドラー関数を終了すると失われます。イベントハンドラを管理するには、グローバル変数または専用オブジェクトを使用する必要があります。私は2番目の解決策を好みます。

もう1つの問題は、Button-Release1にバインドされた2つの関数があることです。私の解決策は、yaxisをバインドせず、createから呼び出すことです。よりクリーンなアプローチを見つけることができます:)

以下の例を参照してください。それは動作するはずです:

from Tkinter import *

root=Tk()

class Handler:

    def __init__(self, w):
        self.w = w
        w.bind("<Button-1>", self.xaxis)
        #w.bind("<ButtonRelease-1>", self.yaxis)
        w.bind("<ButtonRelease-1>", self.create)


    def xaxis(self, event):
        self.x1, self.y1 = (event.x - 1), (event.y - 1)

    def yaxis(self, event):
        self.x2, self.y2 = (event.x + 1), (event.y + 1)

    def create(self, event):
        self.yaxis(event)
        self.w.create_rectangle(self.x1,self.y1,self.x2,self.y2,fill='Black')

w = Canvas(root, width=200, height=200)
w.config(cursor='cross')
w.pack(expand=YES, fill=BOTH)

Handler(w)


root.mainloop()
于 2012-10-11T12:01:06.510 に答える