I want to create two frames next to each other with widgets in a mainframe, but I don't know how to make them both clickable, and I'm sure my code can be cleaned up. Any help is appreciated!
I started off with just making a single frame with widgets and than go from there, but my main problem is that the list constructor can only take one argument. I want to be able to use the self.squares variable for both frames but I'm not sure how to do that so I set up another square dictionary for the second frame but I think that makes things unnecessarily long. Here is my code below. The #here is where I'm having the most trouble.
class Board(tk.Frame):
def __init__(self, parent, length, width): # self=Frame, parent=root
tk.Frame.__init__(self, parent)
self.parent = parent
self.length = length
self.width = width
self.config(height=100 * self.length, width=100 * self.width)
self.frame1 = tk.Frame()
self.frame2 = tk.Frame()
self.pack()
self.squares = {}
self.squares2 = {}
self.ranks = string.ascii_lowercase
self.buttons_pressed = 0
self.turns = 0
self.sq1 = None # first square clicked
self.sq2 = None
self.sq1_button = None # button associated with the square clicked
self.sq2_button = None
self.set_squares()
def select_piece(self, button):
if self.buttons_pressed == 0:
self.sq1 = list(self.squares.keys())[list(self.squares.values()).index(button)] #here
self.sq1_button = button
self.buttons_pressed += 1
elif self.buttons_pressed == 1: # stores square and button of second square selected
self.sq2 = list(self.squares.keys())[list(self.squares.values()).index(button)]
self.sq2_button = button
if self.sq2 == self.sq1: # prevents self-destruction and allows the user to choose a new piece
self.buttons_pressed = 0
return
if True:
self.squares[self.sq2].config(image=self.sq1_button["image"])
self.squares[self.sq2].image = self.sq1_button["image"]
self.squares[self.sq1].config(image=self.white_images["blank.png"]) # clears sq1
self.squares[self.sq1].image = self.white_images["blank.png"]
self.buttons_pressed = 0
return
def set_squares(self): # fills frame with buttons representing squares
for x in range(5):
for y in range(5):
b = tk.Button(self.frame1, bg=self.square_color, activebackground="lawn green")
b.grid(row=8 - x, column=y)
b2 = tk.Button(self.frame2, bg=self.square_color, activebackground="lawn green")
b2.grid(row=8 - x, column=y)
pos = self.ranks[x] + str(y + 1)
self.squares.setdefault(pos, b,) # creates list of square positions
self.squares2.setdefault(pos, b2)
self.squares[pos].config(command=lambda key=self.squares[pos]: self.select_piece(key))
self.squares2[pos].config(command=lambda key=self.squares2[pos]: self.select_piece(key))
def set_pieces(self): # places pieces in starting positions
dict_rank1_pieces = {"a1": "dirt.png", "b1": "fire.png", "c1": "metal.png", "d1": "water.png", "e1": "wood.png"}
for key in dict_rank1_pieces: # inserts images into buttons
starting_piece = dict_rank1_pieces[key]
self.squares[key].config(image=self.white_images[starting_piece])
self.squares[key].image = self.white_images[starting_piece]
self.squares2[key].config(image=self.white_images[starting_piece])
self.squares2[key].image = self.white_images[starting_piece]
self.frame1.pack(side='left')
self.frame2.pack(side='right')
for rank in range(2, 6): # fill rest with blank pieces
for file in range(5):
starting_piece = "blank.png"
pos = self.ranks[file] + str(rank)
self.squares[pos].config(image=self.white_images[starting_piece])
self.squares[pos].image = self.white_images[starting_piece]
self.squares2[pos].config(image=self.white_images[starting_piece])
self.squares2[pos].image = self.white_images[starting_piece]
root = tk.Tk()
root.geometry("800x800")
board = Board(root, 5, 5)
board.import_pieces()
board.set_pieces()
board.mainloop()
If you want to use the same
self.squaresfor both the frames, you need to make the keys (currently they are something like "a1", "b1", etc) unique. One of the suggestion is to use a tuple of(idx, key)instead as the new key:idxis 0 for the first frame, 1 for the second framekeyis the current key used, i.e. "a1", "b1", etcBelow is the required modifications:
Note that currently you have created the two frames with buttons as children of root window, not
Board. Is it what you want actually?Updated
set_pieces()to put images at the very left column of left frame and the very right column of right frame: