gpt4 book ai didi

python - (实例化一组按钮,但只有一个有效

转载 作者:行者123 更新时间:2023-12-05 06:43:34 27 4
gpt4 key购买 nike

我正在尝试为围棋游戏的虚拟棋盘创建 GUI。应该有一个 nxn 方 block 网格,玩家可以在其中放置黑色或白色的棋子。单击一个图 block 会使它从棕褐色(默认)变为黑色,再次单击变为白色,第三次单击返回棕褐色。玩家一可以在一个点上单击一次以将石头放在那里,玩家二可以单击两次(稍后您需要移除石头,因此单击三下可将其重置)。我创建了一个 tile 对象,然后使用嵌套的 for 循环来实例化 9 个 9 个。不幸的是,运行代码似乎只产生 1 个功能 block ,而不是 81 个。这段代码应该可以在任何 python 机器上运行(我使用的是 Python 3.4),因此您可以尝试运行它并亲自查看。谁能指出循环只运行一次的原因?

from tkinter import *
window = Tk()
n = 9

"""
A tile is a point on a game board where black or white pieces can be placed. If there are no pieces, it remains tan.
The basic feature is the "core" field which is a tkinter button. when the color is changed, the button is configured to represent this.
"""
class tile(object):
core = Button(window, height = 2, width = 3, bg = "#F4C364")

def __init__(self):
pass

"""the cycle function makes the tile object actually change color, going between three options: black, white, or tan."""
def cycle(self):

color = self.core.cget("bg")

if(color == "#F4C364"): #tan, the inital value.
self.core.config(bg = "#111111")#white.
elif (color == "#111111"):
self.core.config(bg = "#DDDDDD")#black.
else:
self.core.config(bg = "#F4C364")#back to tan.

board = [] #create overall array
for x in range(n):
board.append([])#add subarrays inside it
for y in range(n):
board[x].append(tile())#add a tile n times in each of the n subarrays
T = board[x][y] #for clarity, T means tile
T.core.config(command = lambda: T.cycle()) #I do this now because cycle hadn't been defined yet when I created the "core" field
T.core.grid(row = x, column = y) #put them into tkinter.

window.mainloop()

最佳答案

正如 mhawke 在他的回答中指出的那样,您需要使 core 成为一个实例变量,以便每个 Tile 都有自己的核心。

正如我在上面的评论中提到的,您还需要修复 Button 的命令回调函数。您在问题中使用的代码将调用 T 当前值的 .cycle() 方法,这恰好是最后创建的图 block 。因此,无论您在何处单击,只有最后一个图 block 会改变颜色。解决此问题的一种方法是在创建当前图 block 时将其作为 lambda 函数的默认参数传递。但是因为您使用 OOP 来创建您的 Tile,所以有更好的方法,您可以在下面看到。

我对您的代码做了一些修改。

虽然许多 Tkinter 示例使用 from tkinter import * 这不是一个好的做法。当您执行 from some_module import * 时,它会将 some_module 中的所有名称带入当前模块(您的脚本),这意味着您可能会不小心用自己的名称覆盖这些名称.更糟糕的是,如果您对多个模块执行 import *,每个新模块的名称都可能与先前模块的名称冲突,并且您无法知道发生了什么,直到您开始获取神秘的错误。使用 import tkinter as tk 意味着您需要做更多的输入,但它使生成的程序更不容易出错并且更易于阅读。

我修改了 __init__ 方法,以便使用窗口和图 block 的 (x, y) 位置调用它(通常使用 x 表示水平坐标,y 表示纵坐标)。每个 Tile 对象现在都跟踪其当前状态,其中 0=空,1=黑色,2=白色。这使得更新颜色更容易。因为我们已经传入窗口和 (x, y),所以我们可以使用该信息将图 block 添加到网格中。磁贴还会记住位置(在 self.location 中),这可能会派上用场。

我已经修改了 cycle 方法,以便它同时更新图 block 的背景 颜色和activebackground。因此,当鼠标悬停在图 block 上时,它会更改为(大致)介于当前颜色和单击它时将变为的颜色之间的颜色。 IMO,这比当鼠标悬停在它上面时总是变成浅灰色的磁贴要好。

我还优化了创建所有图 block 并将它们存储在列表列表中的代码。

import tkinter as tk

colors = (
#background, #activebackground
("#F4C364", "#826232"), #tan
("#111111", "#777777"), #black
("#DDDDDD", "#E8C8A8"), #white
)

class Tile(object):
""" A tile is a point on a game board where black or white pieces can be placed.
If there are no pieces, it remains tan.
The basic feature is the "core" field which is a tkinter button.
when the color is changed, the button is configured to represent this.
"""

def __init__(self, win, x, y):
#States: 0=empty, 1=black, 2=white
self.state = 0
bg, abg = colors[self.state]

self.core = tk.Button(win, height=2, width=3,
bg=bg, activebackground=abg,
command=self.cycle)
self.core.grid(row=y, column=x)

#self.location = x, y

def cycle(self):
""" the cycle function makes the tile object actually change color,
going between three options: black, white, or tan.
"""
#cycle to the next state. 0 -> 1 -> 2 -> 0
self.state = (self.state + 1) % 3
bg, abg = colors[self.state]
self.core.config(bg=bg, activebackground=abg)

#print(self.location)


window = tk.Tk()
n = 9

board = []
for y in range(n):
row = [Tile(window, x, y) for x in range(n)]
board.append(row)

window.mainloop()

关于python - (实例化一组按钮,但只有一个有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32806297/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com