I placed the rectangles over the images. I then bound a click to a call that flipped tiles over by lowering the rectangle below the image. It works for the first call to the function, but when I click another tile, that one won't flip over. The program still registers the second flip because it'll flip everything back over if it's an incorrect match; the only problem is that it won't have the rectangle go under the image.
# ======================================= import statements
import tkinter as tk
import time
import random
import PIL
import PIL.Image as Image
import PIL.ImageTk as ImageTk
# ======================================= class def
class MemoryGame:
def __init__(self):
#initialize window
self.window = tk.Tk()
self.window.title("Sea Life Memory Game")
self.window.minsize(590, 600)
self.window.maxsize(590, 600)
#set main canvas as background
self.canvas = tk.Canvas(self.window, bg="lightblue",
bd=0, highlightthickness=0,
width=590, height=600)
self.canvas.grid(row=0, column=0)
self.canvas.bind("<Button-1>", self.chooseTile)
#establish coordinates for tiles and shuffle image placement
coordinates = [(5,30,105,130), (5,160,105,260), (5,290,105,390), (5,420,105,520), (125,30,225,130), (125,160,225,260), (125,290,225,390), (125,420,225,520), (245,30,345,130), (245,160,345,260), (245,290,345,390), (245,420,345,520), (365,30,465,130), (365,160,465,260), (365,290,465,390), (365,420,465,520), (485,30,585,130), (485,160,585,260), (485,290,585,390), (485,420,585,520)]
imageChoices = ['cropped images/001-turtle.png','cropped images/007-blowfish.png','cropped images/010-jellyfish.png','cropped images/011-starfish.png','cropped images/018-lobster.png','cropped images/028-fish.png','cropped images/033-walrus.png','cropped images/042-goldfish.png','cropped images/045-seal.png','cropped images/046-penguin.png']
random.shuffle(coordinates)
#write title to top of canvas
self.canvas.create_text(295, 15, text="Sea Life Memory Game!",
anchor="center", fill="white",
font="Times 24 bold")
self.selectedTile = None
#initialize counts
coordinateCount = 0
imageCount = 0
self.imageCollection = {}
#for loop to attach images to each rectangle on the canvas
for i in range(len(imageChoices)):
otherDict = {}
x1, y1, x2, y2 = coordinates[coordinateCount]
# if imageCount <= 9:
self.image = ImageTk.PhotoImage(Image.open(imageChoices[imageCount]))
self.image.img = self.image
self.id = self.canvas.create_image(x1, y1, anchor="nw",
image=self.image.img)
self.canvas.create_rectangle(x1, y1, x2, y2, fill="white", outline="white")
coordinateCount = 1
x1, y1, x2, y2 = coordinates[coordinateCount]
self.id = self.canvas.create_image(x1, y1, anchor="nw",
image=self.image.img)
self.canvas.create_rectangle(x1, y1, x2, y2, fill="white", outline="white")
coordinateCount = 1
imageCount = 1
otherDict["faceDown"] = True
self.imageCollection[self.id] = otherDict
#create instructional text
self.canvas.create_text(295, 550, text="Find all the pairs as fast as possible.",
fill="white", font="Times 18", anchor="center")
self.canvas.create_text(295, 570, text="Click on a card to turn it over and find the same matching card.",
fill="white", font="Times 18", anchor="center")
def run(self):
self.window.mainloop()
global list
list = []
def chooseTile(self, event):
# global list
x = event.x
y = event.y
item = self.canvas.find_overlapping(x-5,y-5,x 5,y 5)
list.append(item)
print(len(list))
if len(list) < 2:
self.canvas.tag_lower(list[0][1])
elif len(list) == 2:
self.canvas.tag_lower(list[1][1])
if self.canvas.itemcget(list[0][0], "image") == self.canvas.itemcget(list[1][0], "image"):
list.clear()
else:
time.sleep(1.0)
self.canvas.lower(list[0][0], list[0][1])
self.canvas.lower(list[1][0], list[1][1])
list.clear()
# ======================================= script calls
game = MemoryGame()
game.run()
CodePudding user response:
It is because the update will be performed after chooseTile() returns to tkinter mainloop(). But the images are already reset to lower layer when the function returns, so you cannot see the second selected image.
The simple fix is calling self.canvas.update_idletasks() to force the update to show the second selected image before time.sleep(1.0):
def chooseTile(self, event):
# global list
x = event.x
y = event.y
item = self.canvas.find_overlapping(x-5,y-5,x 5,y 5)
list.append(item)
print(len(list))
if len(list) < 2:
self.canvas.tag_lower(list[0][1])
elif len(list) == 2:
self.canvas.tag_lower(list[1][1])
if self.canvas.itemcget(list[0][0], "image") == self.canvas.itemcget(list[1][0], "image"):
list.clear()
else:
# force the canvas to show the second selected image
self.canvas.update_idletasks()
time.sleep(1.0)
self.canvas.lower(list[0][0], list[0][1])
self.canvas.lower(list[1][0], list[1][1])
list.clear()
CodePudding user response:
I finally got it to work!!
# ======================================= import statements
import tkinter as tk
import random
import PIL.Image as Image
import PIL.ImageTk as ImageTk
# ======================================= class def
class MemoryGame:
def __init__(self):
#initialize window
self.window = tk.Tk()
self.window.title("Sea Life Memory Game")
self.window.minsize(590, 600)
self.window.maxsize(590, 600)
#set main canvas as background
self.canvas = tk.Canvas(self.window, bg="lightblue",
bd=0, highlightthickness=0,
width=590, height=600)
self.canvas.grid(row=0, column=0)
self.canvas.bind("<Button-1>", self.chooseTile)
#establish coordinates for tiles and shuffle image placement
coordinates = [(5,30,105,130), (5,160,105,260), (5,290,105,390), (5,420,105,520), (125,30,225,130), (125,160,225,260), (125,290,225,390), (125,420,225,520), (245,30,345,130), (245,160,345,260), (245,290,345,390), (245,420,345,520), (365,30,465,130), (365,160,465,260), (365,290,465,390), (365,420,465,520), (485,30,585,130), (485,160,585,260), (485,290,585,390), (485,420,585,520)]
imageChoices = ['cropped images/001-turtle.png','cropped images/007-blowfish.png','cropped images/010-jellyfish.png','cropped images/011-starfish.png','cropped images/018-lobster.png','cropped images/028-fish.png','cropped images/033-walrus.png','cropped images/042-goldfish.png','cropped images/045-seal.png','cropped images/046-penguin.png']
random.shuffle(coordinates)
#write title to top of canvas
self.canvas.create_text(295, 15, text="Sea Life Memory Game!",
anchor="center", fill="white",
font="Times 24 bold")
#initialize counts
coordinateCount = 0
imageCount = 0
self.imageCollection = []
#for loop to attach images to each rectangle on the canvas
for i in range(len(imageChoices)):
x1, y1, x2, y2 = coordinates[coordinateCount]
self.image = ImageTk.PhotoImage(Image.open(imageChoices[imageCount]))
self.image.img = self.image
self.id = self.canvas.create_image(x1, y1, anchor="nw",
image=self.image.img)
self.imageCollection.append(self.id)
self.canvas.create_rectangle(x1, y1, x2, y2, fill="white", outline="white")
coordinateCount = 1
x1, y1, x2, y2 = coordinates[coordinateCount]
self.id = self.canvas.create_image(x1, y1, anchor="nw",
image=self.image.img)
self.canvas.create_rectangle(x1, y1, x2, y2, fill="white", outline="white")
coordinateCount = 1
imageCount = 1
self.imageCollection.append(self.id)
#create instructional text
self.canvas.create_text(295, 550, text="Find all the pairs as fast as possible.",
fill="white", font="Times 18", anchor="center")
self.canvas.create_text(295, 570, text="Click on a card to turn it over and find the same matching card.",
fill="white", font="Times 18", anchor="center")
def run(self):
self.window.mainloop()
global lst
lst = []
global matches
matches = 0
def chooseTile(self, event):
global lst
global matches
x = event.x
y = event.y
item = self.canvas.find_overlapping(x-1,y-1,x 1,y 1)
lst.append(item)
if len(lst) < 2:
self.canvas.tag_lower(lst[0][1], lst[0][0])
elif len(lst) == 2:
self.canvas.tag_lower(lst[1][1],lst[1][0])
if self.canvas.itemcget(lst[0][0], "image") == self.canvas.itemcget(lst[1][0], "image"):
matches = 2
lst.clear()
else:
self.window.update_idletasks()
self.window.after(1500)
self.canvas.lower(lst[0][0], lst[0][1])
self.canvas.lower(lst[1][0], lst[1][1])
lst.clear()
if matches == 20:
self.window.update_idletasks()
self.window.after(1000)
self.window.destroy()
# ======================================= script calls
game = MemoryGame()
game.window.mainloop()
