1

私はまだ、2 つの惑星の周りを移動し、それらの間の重力を示すコードに取り組んでいます。移動したい惑星を選択できる2つのボタンを表示するだけで、使いやすくしようとしました。次に、キャンバスをクリックすると、選択した惑星がクリックした場所に移動します。

プログラムは機能しますが、グローバルステートメントで関数chngBと関数を使用するよりも良い方法があるかどうかを知りたいです。Python では、ボタンchngOのパラメーターに関数を割り当てるときに、パラメーターなしで関数を使用することを余儀なくされているとは、まだ信じられません。command

基本的に、次のようなものを書くことが可能かどうかを知りたいですcommand = (a=1) (これが機能しないことはわかっていますが、アイデアはわかります)。また、変数を使用する以外に、おそらく別の方法がありますどの惑星が選択されているか (最後にどのボタンが押されたか) を知ることができます。

私はPython3を使用しています。

from tkinter import *
import math

x, y = 135, 135
a = 0

def gravitation (obj1,obj2):#showing gravitational force between planets 
    a, b, c, d = can.coords (obj1)
    e, f, g, h = can.coords (obj2)
    dist = math.sqrt ((((a+c)/2)-((e+g)/2))**2+(((b+d)/2)-((f+h)/2))**2)
    if dist != 0:
        grav = 6.67384/dist
    else:
        grav = "Infinite"
    str(grav)
    return grav

def chngB ():#Telling Blue planet is selected
    global a
    a = 1

def chngO ():#Telling Orange planet is selected
    global a
    a = 0

def updt ():#Updating gravitation label
    lbl.configure (text = gravitation(oval1, oval2)) 


def moveBlue (event):#Placing blue planet where mouse click on canv
    coo = [event.x-15, event.y-15, event.x+15, event.y+15]
    can.coords(oval1, *coo)
    updt()

def moveOrange (event):#Placing orange planet where mouse click on canv
    coo = [event.x-15, event.y-15, event.x+15, event.y+15]
    can.coords(oval2, *coo)
    updt()

def choice (event):#Function binded to can, move the selected planet (blue = 1, prange = 0)
    if a == 0:
        moveOrange(event)
    else :
        moveBlue(event)

##########MAIN############

wind = Tk() # Window and canvas
wind.title ("Move Da Ball")
can = Canvas (wind, width = 300, height = 300, bg = "light blue")
can.grid(row=0, column=0, sticky =W, padx = 5, pady = 5, rowspan =3)
can.bind ("<Button-1>", choice)
Button(wind, text = 'Quit', command=wind.destroy).grid(row=2, column=1, sticky =W, padx = 5, pady = 5)

oval1 = can.create_oval(x,y,x+30,y+30,width=2,fill='blue') #Planet 1 moving etc
buttonBlue = Button(wind, text = 'Blue Planet', command = chngB)
buttonBlue.grid(row=1, column=1, sticky =W, padx = 5, pady = 5)

oval2 = can.create_oval(x+50,y+50,x+80,y+80,width=2,fill='orange') #Planet 2 moving etc
buttonOrange = Button(wind, text = 'Orange Planet', command = chngO)
buttonOrange.grid(row=0, column=1, sticky =W, padx = 5, pady = 5)

lbl = Label(wind, bg = 'white')#label
lbl.grid(row=4, column=1, sticky =W, padx = 5, pady = 5, columnspan = 3)
gravitation (oval1, oval2)

wind.mainloop()
4

2 に答える 2

1

残念ながら、ステートメント (代入) を含むラムダ式を使用することはできません。Buttonただし、コンストラクターに渡すことができるクロージャーを返すセッター関数を 1 つだけ持つことは簡単です。クロージャーの作成と使用の例を次に示します。

a = 0

def set_a (v):
    def closure ():
        global a
        a = v
    return closure

command = set_a(42)
command()
print a    # prints 42

command = set_a(17)
command()
print a    # prints 17
于 2013-09-03T15:56:10.313 に答える
1

通常、N 個の値のいずれかの間で変数を切り替えるボタンが必要な場合は、一連のラジオボタンを使用します。ラジオボタンを使用すると、ボタンをクリックするたびに変数が自動的に選択されるように変数に関連付けることができます。

例えば:

planet = IntVar()
planet.set(0)

buttonBlue = Radiobutton(wind, text="Blue Planet", variable=planet, value=1)
buttonOrange = Radiobutton(wind, text="Orange Planet", variable=planet, value=0)
...
def choice (event):#Function binded to can, move the selected planet (blue = 1, prange = 0)
    if planet.get() == 0:
        moveOrange(event)
    else :
        moveBlue(event)

本当に通常のボタンを使用したい場合は、2 つではなく 1 つのコールバックでそれを行い、lambdaorを使用functools.partialして新しい値を渡すことができます。

例えば:

buttonBlue = Button(wind, text = 'Blue Planet', command = lambda: change(1))
buttonOrange = Button(wind, text = 'Blue Planet', command = lambda: change(0))
def change(newValue):
    global a
    a = newValue
于 2013-09-03T17:18:50.147 に答える