1

I'm still working on a code that moves around two planets and shows the gravitational force between them. I tried to make it easier to use by just showing two buttons that allow to select the planet you want to move. Then you can click in the canvas and the selected planet will move where you've clicked.

The programm works, but I'd like to know if there is a better way to write it then using the chngB and chngO functions with global statements. I still can't believe that in Python you are forced to use a function without parameters when assigning it to the command parameter of a button.

Basically I'd like to know if it's just possible to write something like command = (a=1) (I know that this doesn't work, but you get the idea.) Also, there probably just is another way of doing it than having to use a variable to know which planet is selected (which button has been pressed last).

I use Python 3.

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

通常,如果您想要一个按钮在 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)

如果你真的想使用一个常规按钮,你可以用一个回调而不是两个来做到这一点,然后使用lambdaorfunctools.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 回答
1

不幸的是,你不能有一个包含语句(赋值)的 lambda 表达式。但是你可以很容易地只有一个 setter 函数,它返回一个可以传递给Button构造函数的闭包。下面是一个创建和使用闭包的例子:

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 回答