如何将两个或多个参数传递给Button命令?

时间:2019-08-05 19:07:39

标签: python python-3.x tkinter

我想在函数中传递2个变量参数,以将其分配给Button command。这些变量会在for循环内更改,该循环还会创建按钮。

主要受一些herehere的最高启发所启发,这是我根据阅读内容尝试解决此问题的失败尝试:

我尝试使用partial

self.dct[(i, j)] = Button(command=partial(self.on_click, i, j))

另一种尝试:

self.dct[(i, j)] = Button(command=partial(partial(self.on_click, i), j))

另一个:

self.dct[(i, j)] = Button(command=partial(self.on_click, [i, j]))

..你猜怎么着?

tup = [i, j]
self.dct[(i, j)] = Button(command=partial(self.on_click, tup))

然后,lambda

self.dct[(i, j)] = Button(command=lambda i=i, j=j: self.on_click(i, j))

这是我的代码:

import tkinter as tk

from functools import partial


class Board(tk.Frame):
    board = None
    images = None
    tile = None

    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        self.tile = {}
        for i in range(10):
            for j in range(10):
                self.tile[(i, j)]['btn_obj'] = tk.Button(self.board, command=partial(partial(self.on_click, i), j))

    def on_click(self, i, j):
        print("X: {}, Y:{}".format(j, i))

partial总是会导致如下错误:

TypeError: on_click() takes 2 positional arguments but 3 were given

参数数量总是不匹配。

与此同时,lambda获得了错误的变量值,从而导致tkinter方面出现了一些错误。

1 个答案:

答案 0 :(得分:2)

您问题中的lambda应该起作用:

<p>Example Situation</p>
<table>
  <tr>
    <td>
      <p id="question1">Question 1</p>

      <input type="radio" name="question1" id="yes1" value="yes">
      <label for="yes1">Yes</label>
      <input type="radio" name="question1" id="no1" value="no">
      <label for="no1">No</label>
    </td>
    <td>
      Answer 1
    </td>
  </tr>

  <tr>
    <td>

      <p id="question2">Question 2</p>

      <input type="radio" name="question2" id="yes2" value="yes">
      <label for="yes2">Yes</label>
      <input type="radio" name="question2" id="no2" value="no">
      <label for="no2">No</label>
    </td>
    <td>
      Answer 2
    </td>
  </tr>
</table>

这会将值tk.Button(self.board, command=lambda i=i, j=j: self.on_click(i,j)) i绑定为lambda参数的默认值。

我个人更喜欢lambda而不是lambda,这主要是因为我不必导入functools模块。如果您希望使用partial,它应该看起来像您的第一个示例:

j

在两种情况下,创建按钮时,都会根据tk.Button(self, command=partial(self.on_click, i, j)) on_click的值向ij传递正确的值。

这是一个基于您的代码的示例,但是为了清楚起见,删除了一些不必要的代码:

import tkinter as tk
from functools import partial


class Board(tk.Frame):
    def __init__(self, parent, method):
        tk.Frame.__init__(self, parent, bd=2, relief="sunken")
        for i in range(10):
            for j in range(10):
                if method == "lambda":
                    button = tk.Button(self, command=lambda i=i, j=j: self.on_click(i,j))
                else:
                    button = tk.Button(self, command=partial(self.on_click, i, j))
                button.grid(row=i, column=j)

    def on_click(self, i, j):
        print("X: {}, Y:{}".format(j, i))

root = tk.Tk()
board1 = Board(root, method="lambda")
board2 = Board(root, method="partial")
board1.pack(side="top", fill="both", expand=True)
board2.pack(side="top", fill="both", expand=True)
root.mainloop()