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()