如何在Tkinter中打印调用函数的按钮

时间:2018-06-21 14:17:36

标签: python python-3.x tkinter lambda

我一直在写一段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()

3 个答案:

答案 0 :(得分:1)

要使函数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很酷,绝对值得阅读更多。

答案 1 :(得分: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 :(得分:0)

答案竟然是按钮绑定(感谢@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)