【问题标题】:How to print the button that calls a function in Tkinter如何打印在 Tkinter 中调用函数的按钮
【发布时间】:2018-06-21 14:17:35
【问题描述】:

我一直在编写一段生成按钮数组的 Tkinter 代码。每个按钮调用相同的函数。函数 (button_press) 应该打印单击它的按钮。我应该输入什么代码让 button_press 打印按下它的按钮?

我听说 Lambda 很有帮助,但我不确定该怎么做。

import tkinter as tk
import random

class App(tk.Frame):
    def __init__(self, master = None):
        super().__init__(master)
        self.grid()
        self.create_buttons()
        self.create_mines()

    def create_buttons(self):
        self.buttons = []
        for y in range(16):
            self.buttons.append([])
            for x in range(30):
                self.buttons[y].append(x)
                self.buttons[y][x] = tk.Button(command = self.button_press)
                self.buttons[y][x].grid(column = str(x), row = str(y))

    def create_mines(self):
        self.mine_list = []
        for mines in range(99):
            self.yValue = random.randint(0, 15)
            self.xValue = random.randint(0, 29)
            if self.buttons[self.yValue][self.xValue] in self.mine_list:
                mines += 1
            else:
                self.mine_list.append(self.buttons[self.yValue][self.xValue])

    def button_press(self):
        #?????

root = tk.Tk()
app = App(master = root)
app.mainloop()

【问题讨论】:

  • effbot 在记录所有 tkinter 方面做得很好
  • 谢谢!我去看看。
  • 好的,我已经读完了,widget 是正确的事件属性吗?

标签: python python-3.x tkinter lambda


【解决方案1】:

事件处理程序获取一个参数,一个事件,它具有多个属性,包括捕获事件的小部件。不幸的是,命令函数没有参数,甚至没有捕获调用命令的点击的小部件。

所以如果你想让不同按钮的命令函数做不同的事情,你必须传递不同的函数。在您的情况下,您需要 30 x 16 = 480 个不同的功能。替换

            self.buttons[y][x] = tk.Button(command = self.button_press)

例如,

            self.buttons[y][x] = tk.Button(
                command=lambda x=x, y=y: print(f'{x},{y}'))

这是为每个按钮创建不同功能的多种方法之一。这是对这个问题的常规回答。

另一种方法是不使用按钮命令选项,而是将按钮单击绑定到处理程序,该处理程序获取包含单击按钮的事件。然后将有关单击处理程序所需的每个按钮的信息添加到每个按钮,而不是添加到命令函数。这是游戏的完整开发版本,用于测试。

import tkinter as tk
import random


class App(tk.Frame):
    def __init__(self, master, rows, columns):
        self.master = master
        self.rows = rows
        self.columns = columns
        super().__init__(master)
        self.grid()
        self.create_buttons()
        self.create_mines()

    def create_buttons(self):
        self.buttons = []
        for y in range(self.rows):
            self.buttons.append([])
            for x in range(self.columns):
                button = tk.Button()
                button.y = y
                button.x = x
                button.mine = False
                button.grid(column=x, row=y)
                button.bind('<Button-1>', self.button_press)
                self.buttons[y].append(button)

    def create_mines(self):
        self.mines = set()
        mine_num = 0
        while mine_num < self.rows * self.columns // 5:
            x = random.randint(0, self.columns-1)
            y = random.randint(0, self.rows-1)
            button = self.buttons[y][x]
            if button not in self.mines:
                button.mine = True
                button['background'] = 'red'
                self.mines.add(button)
                mine_num += 1

    def button_press(self, event):
        b = event.widget
        label = 'Mine' if b.mine else 'Free'
        print(f'{label} {b.x}-{b.y}')


root = tk.Tk()
app = App(root, rows=16, columns=30)
app.mainloop()

对于游戏,在点击时暴露地雷,而不是在创建时暴露地雷;0)。

【讨论】:

    【解决方案2】:

    要使函数button_press 能够打印单击它的按钮,您需要将该按钮作为变量传递。

    所以button_press 的函数定义应该类似于

    def button_press(self, x, y):
        print("Button (%d,%d)" % (x,y))
    

    当你创建按钮时,你可以做类似的事情

    self.buttons[y][x] = tx.Button(command = (lambda : self.button_press(x,y)))

    这意味着当按钮被点击时,它会调用 lambda 函数,该函数使用按钮的 x 和 y 调用 button_press。 Lambda 非常酷,绝对值得一读。

    【讨论】:

    • 这似乎是朝着正确方向迈出的一步,但它总是打印以下内容:Button (29,15)
    【解决方案3】:

    答案竟然是按钮绑定(感谢@pstatix)!

    添加

    self.buttons[y][x].bind('<Button-1>', self.button_press)
    

    之后

    self.buttons[y][x].grid(column = str(x), row = str(y))
    

    改变

    def button_press(self):
    

    def button_press(self, event):
        print(event.widget)
    

    并将其移至上方

    def create_buttons(self)
    

    【讨论】:

      猜你喜欢
      • 2019-06-23
      • 1970-01-01
      • 2013-08-21
      • 1970-01-01
      • 2015-09-23
      • 1970-01-01
      • 2021-08-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多