简体   繁体   中英

Grid of buttons: Change color of one when it is clicked

So I have a grid of buttons I've created like this (using Tkinter on Python 3.4):

from tkinter import *

vText = [ "A","B","C","D","E","F","G","H","I","J" ]
boat  = [ "A1","A2","A3" ]
shots = []

def press( pos, b, pos2 ):
    if pos in shots:
        print( "You've chosen this already!" )
    else:
        shots.append( pos )
        if pos in boat:
            print( "Hit!" )
            b[pos2].configure( bg = "red", fg = "white" )
        else:
            print( "Miss." )
            b[pos2].configure( bg = "blue", fg = "white" )

root   = Tk()
button = []
row    = []
column = []
for a in range( 1, 102 ):
    button.append( a )
    row.append(    a )
    column.append( a )

for i in range( 0, 10 ):
    for j in range( 1, 11 ):
        p2 = i * 10 + j
        button[p2] = Button( root, text    = vText[i] + str(j),                   \
                                   command = lambda i=i, j=j, position=vText[i] + str(j): press( position, button, p2 ), \
                                   padx    = 25,                                  \
                                   pady    = 25,                                  \
                                   bg      = "#66CCCC"                            \
                                   )
        button[p2].grid( row = i, column = j )

root.wm_title( "Enemy grid" )
root.mainloop()

As you can see, I've tried (in the press() definition ) to do the job, but pos2 only is able to reference the last one because it uses i and j in the for loops.

This is part of a BattleShip code, so there are a few bits and pieces I've added since this. However, the question is the same. I want to be able to click one, and have it change color when it is clicked. It needs to be possible for all 100 buttons created. Additionally, I need it to become red if it is on a hit, or blue if it is a miss.

Thanks in advance.

In order for buttons in Tkinter (or any GUI framework, though the terms and techniques will very), you need to bind a function to the button.

For example:

from functools import partial

def my_func_name(sequence, index):
    widget = sequence[index]
    widget.configure(bg='white') #  for example

for i in range(0,10):
    for j in range(1,11):
        p2 = i * 10 + j
        par = partial(my_func_name, button, p2)
        button[p2] = Button(root, text = vText[i] + str(j), command=par, padx=25, pady=25, bg = "#66CCCC")
        button[p2].grid(row=i, column=j)

Effbot wrote a pretty good book on Tkinter (free), there is also Tkdocs , which is a wonderful tutorial that covers the basics in more detail than is fitting of an SO question.

This answer has been edited to reflect a boneheaded gaff I made when I first answered the question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM