问题描述:

from tkinter import *

class GameBoard(Frame):

def __init__(self):

top = Toplevel()

Frame.__init__(self)

self.master.title("test")

self.grid()

#button frame

self.__buttonPane = Frame(self)

self.__buttonPane.grid()

#buttons

self.__buttonA1 = Button(self.__buttonPane,text = "A1",command = self._test("A"))

self.__buttonA1.grid()

def _test(self,test):

if self.__buttonA1["state"] == NORMAL:

print(test)

def main():

GameBoard().mainloop()

main()

This code will not work due to the variable and if I remove the variable test and make it

from tkinter import *

class GameBoard(Frame):

def __init__(self):

top = Toplevel()

Frame.__init__(self)

self.master.title("test")

self.grid()

#button frame

self.__buttonPane = Frame(self)

self.__buttonPane.grid()

#buttons

self.__buttonA1 = Button(self.__buttonPane,text = "A1",command = self._test)

self.__buttonA1.grid()

def _test(self):

if self.__buttonA1["state"] == NORMAL:

print("hi")

def main():

GameBoard().mainloop()

main()

How would I fix my code so it would allow for input of a variable?

This is just a test I am doing so I can make it work in a much bigger code.

网友答案:

When you specify command = self._test, self._test is a function that will be called. self._test("A") is not a function, it's a call to a function (that returns None because there's no return statement in the definition).

You can write 'a function that calls self._test("A") as either lambda: self._test("A"), or functools.partial(self._test, "A"), or explicitly in GameBoard.__init__:

def _f():
    self._test("A")
self.__buttonA1 = Button(self.__buttonPane,text = "A1",command = _f)
网友答案:

The problem is when you do command = self._test("A"), you are calling the function, and using the returned value (which is None in this case).

The solution is to use functools.partial(), which takes a function and some values, then gives you a new function which just calls the given function with the values you passed it (and any additional others you pass when you run it):

command = functools.partial(self._test, "A")

You could also do this manually by making your function return a function:

def _test(self, test):
    def f(self):
        if self.__buttonA1["state"] == NORMAL:
           print(test)
    return f

Do note that this would impair your ability to call _test() normally elsewhere.

网友答案:

When creating handlers for buttons, it is a good idea to pass the button itself to the handler. That way, a single handler can handle many buttons, and the handler is free to examine all the properties of the button.

Here's a simple way to achieve that based on your code:

    self.__buttonA1 = Button(self.__buttonPane,text = "A1")
    self.__buttonA1.grid()
    self._connect_button(self.__buttonA1, self._test)
    self.__buttonA2 = Button(self.__buttonPane,text = "A2")
    self.__buttonA2.grid()
    self._connect_button(self.__buttonA2, self._test)

  def _connect_button(self, button, handler):
    button['command'] = lambda: handler(button)

  def _test(self, button=None):
    if button is not None:
      print("test:text:", button["text"])
      print("test:state", button["state"])
相关阅读:
Top