问题
Like many other python beginners, I am playing around with GUIs (tkinter). For my little project, I wanted to create a grid of 5x5 buttons, that is 25 buttons in total, and interact with them: when you click on any of those 25 buttons, some buttons will change around the clicked button. I won't go into much details about what I want the final result to be, unless you think it is relevant. You will find bellow a code snippet that was adapted for this question in particular.
The question, btw, is:
How to make some specific buttons react to the event of another button being pressed in this situation?
Added more information about this situation, I'll formulate my question like this :
Given an array of 25 buttons generated by for loops, how to target specific buttons in order to interact with their parameters (for example: the parameter 'bg'. One button is cliked, another changes colours), considering that those buttons were not stored into variables that would allow an explicit access (for example: butt = tk.Button(...). Changing parameters of butt would be easy because the widget was explicitly assigned to a variable. Here, no variable assignment, just an iterative creation of widgets)
I tried looking for answers for a long time without success, and that is certainly because I am looking in the wrong direction.
If you run the code bellow, you will get a 5x5 button grid. What I want is that for example all the surrounding buttons change their background colour to green if I click on any button.
import tkinter as tk
# --- functions ---
def draw_board():
frame_board = tk.Frame(root)
frame_board.pack()
def callback(button):
button['relief'] = 'sunken'
button['bg'] = 'lightgrey'
button['state'] = 'disabled'
def draw_tile(container, number):
tile_1 = tk.Button(container,
text='1',
width=6,
height=3,
relief='sunken',
bg='lightgrey',
state='disabled')
tiles = tk.Button(container,
text='?',
command=lambda: callback(tiles),
width=6,
height=3)
if number == 1:
return tile_1
else:
return tiles
r, c = 0, 0
for i in range(1,26):
c += 1
if i in range(1,26,5):
r += 1
c = 0
draw_tile(frame_board, i).grid(row=r,
column=c,
sticky='wens',
padx=10,
pady=10)
else:
draw_tile(frame_board, i).grid(row=r,
column=c,
sticky='wens',
padx=10,
pady=10)
# --- main ---
root = tk.Tk()
root.geometry('400x400')
start_button = tk.Button(root,
text='START',
command=draw_board)
start_button.place(relx=.5,
rely=.5,
anchor='center')
root.mainloop()
This is my first question on SO so please tell me if it was not complete, or if it needed more precisions. I tried to make the code lighter than the one I am working on, but I can make it even more simple if needed (I think)
Thank you !
EDIT: if you see anything in my code that SHOULD be modified for the sake of clarity/effectiveness/usage etc. please tell me, even if it does not answer my twisty question.
回答1:
I actually asked a question similar to this a few years ago when I was starting out:
tkinter: changing button attributes for buttons created in loop
It would be much easier if you store the buttons somewhere when they are created:
(I removed some redundant code as well.)
import tkinter as tk
# --- functions ---
def draw_board(buttons):
frame_board = tk.Frame(root)
frame_board.pack()
def surround(buttons, num):
edges = {'N': list(range(0,5)), 'E': list(range(4,25,5)),
'S': list(range(20,25)), 'W': list(range(0,25,5))}
encircle = {'N':-5, 'NE':-4, 'E':1, 'SE':6, 'S':5, 'SW':4, 'W':-1, 'NW':-6}
for direction in edges:
# determine if selected button is on an edge
if num in edges[direction]:
# if button is on an edge, set encircle direction False
for d in encircle:
if direction in d:
encircle[d] = False
for key, val in encircle.items():
if val: # check that its not False
buttons[num + val].config(bg = 'green')
def callback(buttons, num):
buttons[num].config(relief = 'sunken', bg = 'lightgrey', state = 'disabled')
surround(buttons, num)
def draw_tile(container, buttons, number):
tile = tk.Button(container, text='?', width=6, height=3,
command=lambda num=number: callback(buttons, num))
return tile
r, c = 0, 0
for i in range(0,25):
c += 1
buttons.append(draw_tile(frame_board, buttons, i)) # append button
if i in range(0,25,5):
r += 1
c = 0
# grid last button in list
buttons[-1].grid(row=r, column=c, sticky='wens', padx=10, pady=10)
# --- main ---
root = tk.Tk()
root.geometry('400x400')
buttons = [] # declare list
start_button = tk.Button(root, text='START',
command=lambda:draw_board(buttons))
start_button.place(relx=.5, rely=.5, anchor='center')
root.mainloop()
Now buttons
is a list containing each button, and you can edit their properties using the buttons[0].config()
method
来源:https://stackoverflow.com/questions/59305047/gui-tkinter-how-to-access-parameters-of-specific-buttons