[英]tkinter button color won't change (non-click event)
我创建了一个程序,让一名骑士绕着棋盘移动,从一个随机位置开始,在不触及同一个方格的情况下触及每个方格。 我试图通过在骑士移动时将正方形(这是一个按钮)的颜色更改为红色来使用 tkinter 来显示此动作。
棋盘由 tkinter 个按钮组成,它们与“正方形”class 相关。程序在创建网格时设置正确的 colors,但在执行过程中不会更改它们。
这是简化的代码(按照指示提供)。 简化后的代码并不是全部代码,只是创建棋盘并将骑士放置在随机位置的实例。 当骑士被放置时,按钮的颜色应该改变。
from tkinter import *
from tkmacosx import Button
import random
import sys
WIDTH = 800
HEIGHT = 1000
GRID_SIZE = 8
class Square:
board = []
def __init__(self, x, y, touched=False):
self.touched = touched
self.board_btn_object = None
self.x = x
self.y = y
def create_btn_object(self, location):
btn = Button (
location,
width=100,
height=100,
text= f"{self.x}, {self.y}",
bg=None
)
self.board_btn_object = btn
Square.board.append(self)
@property
def is_touched(self):
self.touched = True
self.board_btn_object.configure(bg="red")
@staticmethod
def randomlocation():
return random.choice(Square.board)
def __repr__(self):
return f"Square({self.x}, {self.y}) touched={self.touched}"
class Knight:
def __init__(self, x, y):
self.x = x
self.y = y
def main():
root = Tk()
root.configure(bg='blue')
root.geometry(f'{WIDTH}x{HEIGHT}')
root.title("chess chaser")
root.resizable(False, False)
top_frame = Frame(
root,
bg = "red",
width = WIDTH,
height = height_prct(10)
)
top_frame.place(x=0, y=0)
bottom_frame = Frame(
root,
bg="black",
width = WIDTH,
height = height_prct(10)
)
bottom_frame.place(x=0, y=height_prct(90))
center_frame = Frame(
root,
bg = "green",
width = WIDTH,
height = height_prct(80)
)
center_frame.place(
x=0,
y=height_prct(10)
)
make_board(center_frame)
top_menu(top_frame)
root.mainloop()
def height_prct(percentage):
return (HEIGHT / 100) * percentage
def width_prct(percentage):
return (WIDTH / 100) * percentage
def top_menu(top_frame):
run = Button (
top_frame,
width = 100,
height = 50,
text=f"Run",
command = play_game
)
run.place(x=30, y=10)
def make_board(center_frame):
for x in range(GRID_SIZE):
for y in range(GRID_SIZE):
b = Square(x, y)
b.create_btn_object(center_frame)
b.board_btn_object.grid(
column=x, row=y
)
if (x+y) %2 ==0:
b.board_btn_object.configure(bg="grey50")
return
def play_game():
knight = place_knight()
sys.exit("Done")
def place_knight():
coords = Square.randomlocation()
coords.is_touched
x = coords.x
y = coords.y
knight = Knight(x, y)
return knight
if __name__ == "__main__":
main()
我试过使用 self.board_btn_object.change(bg="red") and.update and.after.... 没有任何方法可以改变颜色。
如果我更改代码并绑定左键单击以将按钮更改为红色,则可以正常工作; 但是,我希望它在 KNIGHT 放置在那里时发生变化。
你只是把一切都复杂化了。 创建一个单元格 class 并在其中保留 x,y 和 iftouched 的信息。 通过这种方式,您可以轻松地将新功能添加到单元格中。 创建一个板并在其中创建一个数组。 创建单元格实例并放入该数组。 无论你做什么,你都应该在这个板子里做。 定义规则、移动功能等。GUI 应该只是这个假想板的幻觉。 当事情变得复杂时,您只需根据您的电路板更新您的用户界面!
import tkinter as tk
import random
GRID_SIZE = 8
#this is cell which going to keep information
class cell:
def __init__(self,x,y,IsTouched=False):
self.x= x
self.y = y
self.touched = IsTouched
class board:
def __init__(self):
self.initializeBoard()
self.knight = [0,0]
self.placeKnightRandomly()
def moveKnight(self,x,y):
#if knight can move in the board, return True so that
#we can show in the GUI.
if(self.board[x][y].touched):
return False
else:
self.knight = [x,y]
print(f"Knight new position:{x},{y}")
return True
def initializeBoard(self):
#This function creates board from zero.
#if you want to reset board, simple run this function.
self.board = []
for row in range(GRID_SIZE):
line = []
for column in range(GRID_SIZE):
line.append(cell(row,column))
self.board.append(line)
def placeKnightRandomly(self):
#place knight randomly
x = random.randint(0,7)
y = random.randint(0,7)
self.knight = [x,y]
self.board[x][y].touched = True
print("knight:",x,y)
class GUI:
def __init__(self):
self.mw = tk.Tk()
self.mw.geometry("800x800")
self.board = board()
self.buttonFrame = tk.Frame(self.mw)
self.buttonFrame.place(relx=0,rely=0,relheight=1,relwidth=1)
self.updateButtons()
self.mw.mainloop()
def updateButtons(self):
for child in self.buttonFrame.winfo_children():
child.destroy()
self.buttonsList = []
for lines in self.board.board:
buttons = []
for column in lines:
x = column.x
y = column.y
btn = tk.Button(self.buttonFrame,text=f"{x},{y}",width=12,height=5)
if(self.board.board[x][y].touched):
btn.configure(bg="red")
#lets connect a buttons to functions. Send x and y as parameters.
btn.configure(command=lambda x = x,y=y:self.touchInto(x,y) )
btn.grid(row=x,column=y)
buttons.append(btn)
self.buttonsList.append(buttons)
def touchInto(self,x,y):
#when you clicked button, this function going to run
if(self.board.moveKnight(x,y)):
self.board.board[x][y].touched = True
self.buttonsList[x][y].configure(bg="red")
else:
print("cannot move!")
if __name__ == "__main__":
GUI()
创建一个单元格 class 并保留您制作的变量的信息。 通过这种方式,您可以轻松地将新功能添加到单元格中。 创建一个板并在其中创建一个数组。 创建单元格实例并放入该数组。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.