今天我們利用canvas繪制、刪除圖片的的函數,以及鼠標事件的綁定來制作一個簡單的九宮格拼圖游戲。
首先從網上下九張圖,它們是把一張圖分割成了九宮圖,打亂后顯示在canvas畫布上。
接下來我們只要實現圖片的選中與拖動即可,用到了鼠標左鍵、按下并拖動左鍵、鼠標右鍵和鼠標移動四個事件的綁定。
其他的并不難,直接看完整代碼和注釋吧:
from tkinter import *
import tkinter as tk
from PIL import Image, ImageTk
import random
a=0 #用來記錄繪制的圖片編號,其中1-9為初始的9張
List = [1,2,3,4,5,6,7,8,9]
random.shuffle(List) #打亂圖片順序
root = Tk()
root.title("拼圖游戲")
root.geometry("1400x690")
canvas = Canvas(root,width=1400, height=690)
canvas.pack()
#獲得鼠標位置
def callback(event):
global x,y
x = event.x
y = event.y
#刪除剛繪制的圖片
def delete(event):
try:
if a>14: #前九張和五條邊界線不能刪除
canvas.delete(a)
except:
return
#根據鼠標位置,確定當前區域,即選中的圖片編號
def pick(event):
global a
if x<=230 and y<=230:
a=1
elif 230<x<=460 and y<=230:
a=2
elif 460<x<=690 and y<=230:
a=3
elif x<=230 and 230<y<=460:
a=4
elif 230<x<=460 and 230<y<=460:
a=5
elif 460<x<=690 and 230<y<=460:
a=6
elif x<=230 and 460<y<=690:
a=7
elif 230<x<=460 and 460<y<=690:
a=8
elif 460<x<=690 and 460<y<=690:
a=9
#刪除并重新繪制選中的圖片
def call(event):
global a,aa
if a>14: #原圖和邊界線不刪除
canvas.delete(a)
exec('canvas.create_image(x,y,image=var{})'.format(i))
a=aa+1 #記錄新的圖片編號,aa的初始值為14
aa+=1
#九張圖片的位置,以圖片中心點為基準
lc=[[115,115],[230+115,115],[460+115,115],[115,230+115],[230+115,230+115],[460+115,230+115],[115,460+115],[230+115,460+115],[460+115,460+115]]
#繪制初始九張圖
for j in range(1,10):
load = Image.open("pt/%s.png"%List[j-1])
exec('var{}= ImageTk.PhotoImage(load)'.format(j)) #批量創建變量
exec('canvas.create_image(lc[j-1][0],lc[j-1][1],image=var{})'.format(j))
#繪制初始五條邊界線
canvas.create_line(690,0,690,690)
canvas.create_line(690,230,1400,230,fill="white")
canvas.create_line(690,460,1400,460,fill="white")
canvas.create_line(920,0,920,690,fill="white")
aa=canvas.create_line(1150,0,1150,690,fill="white")
#綁定鼠標事件
canvas.bind("<B1-Motion>",call) #拖動左鍵,移動圖片
canvas.bind("<Button-1>",pick) #點擊左鍵,確定圖片編號
canvas.bind("<Button-3>",delete) #右鍵刪除
root.bind("<Motion>",callback) #移動鼠標獲取坐標
root.mainloop()
注意事項:
代碼中的難點是如何動態創建變量。
exec('canvas.create_image(x,y,image=var{})'.format(i))
之所以必須動態創建,是因為用上面這句賦給image值的時候,傳進來的變量不能在后續發生改變,否則就會顯示不出圖片。因此顯示九張圖,就得創建九個變量var1、var2……var9,而不能用同一個變量給image傳值。為了簡便,我們只能動態地創建變量和調用。
另外,注意call函數中,之所以通過aa來給a賦值,而不是直接用:
exec('a=canvas.create_image(x,y,image=var{})'.format(i))
原因在于,exec里面賦值語句是不生效的(我也不知道為啥),a不會在里面被賦值。