Tkinter按钮列表超出索引

时间:2019-02-25 04:43:19

标签: python tkinter

我正在尝试将我在python中编写的代码改编为使用tkinter的程序。 我为董事会中的每个字符(X和O)列出了一个列表,并列出了一个按钮列表。每个按钮在按下时应根据情况从“”更新为“ X”或“ O”。其余代码尚未完成,但这并不是问题所在。

我使用marcar(i,j,texto)作为更新按钮文本的功能,以按钮列表中按钮的位置为参考。但在第25行中,显示“列表索引超出范围”的错误。我在第31行中使用了相同的命令。我想这是因为在创建按钮的第29行中,用于创建按钮的事情之一是方法marcar(),因为它尚未被使用。在列表中创建了其他任何对象,我无法引用它。

我找不到任何制作按钮的解决方案,当按下按钮时,它会使用引用同一按钮的方法,因为要创建该按钮,我需要功能。

from tkinter import *

lista = [[" ", " ", " "],
         [" ", " ", " "],
         [" ", " ", " "]]

buttons = [[], [], []]

vitx = 0
vito = 0

root = Tk()

turno = Label(root, text="Turno de X",font=("Arial",15))
turno.grid(row = 1,column = 1)

vitoriasx = Label(root, text="Vitórias de X:"+str(vitx), font=("Arial",8))
vitoriasx.grid(row = 1,column = 0)

vitoriaso = Label(root, text="Vitórias de O:"+str(vito), font=("Arial",8))
vitoriaso.grid(row = 1,column = 2)

def marcar(i,j,texto):
    lista[i][j] = texto
    buttons[i][j].config(text= texto)

for i in range(0,3):
    for j in range(0,3):
        buttons[i].append(Button(root,text=lista[i][j],command = marcar(i,j,"x")))
        buttons[i][j].grid(row = i+2,column = j)
        buttons[i][j].config(height=6, width=13)


root.mainloop()

2 个答案:

答案 0 :(得分:1)

您需要为这组循环构建适当的lambda函数,以使按钮将正确的信息发送给函数,而又不会导致命令在初始化时执行。

在python中,当您需要保存对函数的引用时,有2个选项。

对于不带参数的函数,您可以省略括号()来保存对该函数的引用,或者如果需要传递参数,则可以使用lambda表达式。

如果您确实使用了lambda表达式,并且像在此处那样在循环中更改了变量,则需要定义每个循环中每个参数的含义,否则这些值将等于最后一个循环的值。

例如,如果您简单地使用lambda而不在每个循环中定义变量,那么最终将得到所有都发送相同数据的按钮。

这里是一个例子:

import tkinter as tk


root = tk.Tk()

def marcar(i, j, texto):
    print(i, j, texto)

for i in range(0, 3):
    for j in range(0, 3):
        tk.Button(root, text='button {}.{}'.format(i, j), command=lambda: marcar(i, j, "x")).grid(row=i, column=j)

root.mainloop()

结果:

enter image description here

但是,如果您在每个循环的lambda中定义值,则每个按钮将获得正确的值。

示例:

import tkinter as tk


root = tk.Tk()

def marcar(i, j, texto):
    print(i, j, texto)

for i in range(0, 3):
    for j in range(0, 3):
        tk.Button(root, text='button {}.{}'.format(i, j), command=lambda i=i, j=j: marcar(i, j, "x")).grid(row=i, column=j)

root.mainloop()

结果:

enter image description here

答案 1 :(得分:0)

问题是您不能像这样在var img: HTMLImageElement; function showImageFile( file: File ): void { let oldSrc = img.src; let objectURI = URL.createObjectURL( file ); img.src = objectURI; if( oldSrc ) URL.revokeObjectURL( oldSrc ); } 中传递参数。您必须将command更改为command=marcar(i,j,"x")。您可以找到herehere的说明。尝试以下代码:

command=lambda: marcar(i, j, "x")