通過 tkinter 采用非面相對象式實現彈球小游戲(使用蹩腳式面相對象實現)。

#!/user/bin env python # author:Simple-Sir # time:2020/8/3 17:12 import tkinter,time,random x = 1 y = 1 score = 0 # 分數 level = 1 # 關卡 # 創建顏色列表 color_li = ['#feeeed','#f391a9','#fab27b','#454926','#181d4b','#a3cf62','#45b97c','#008792','#2585a6'] # 創建窗口 tk = tkinter.Tk() # 聲明一個TK,初始化一個“窗口”(畫一個窗口) tk.title('彈球游戲') # 窗口名稱 tk.resizable(width=False,height=False) # 窗口是否可變(長、寬),也可用0,1表示 tk.wm_attributes('-topmost',1) # 窗口永遠在前 # 創建畫布 canvas = tkinter.Canvas(tk,width=600,height=500,bd=0) # 創建一個“畫布” # 創建畫布組件 filename = tkinter.PhotoImage(file="bg.png") # 獲取一張圖片 canvas.create_image(300, 250,image=filename) # 將圖片添加到畫布,作為背景 id_ball = canvas.create_oval(10, 10, 30, 30, fill=random.choice(color_li),width=0) # 定義一個球 id_paddle = canvas.create_rectangle(0,400,150,420,fill=random.choice(color_li),width=0) # 定義木板 canvas.move(id_paddle,225,0) canvas.create_text(400, 20, text='關卡:',fill='white',font=('宋體', '20')) canvas.create_text(500, 20, text='得分:',fill='white',font=('宋體', '20')) id_level = canvas.create_text(450, 20, text=1,fill='white',font=('宋體', '20')) id_score = canvas.create_text(550, 20, text=0,fill='white',font=('宋體', '20')) id_start_game = canvas.create_text(300,200,text='Start Game.',font=('宋體', '30'),fill=random.choice(color_li)) canvas.pack() # 將畫布添加到窗口中 tk.update() # 刷新窗口 wh = canvas.winfo_height() # 獲取窗口高度(update刷新之后才能獲取) ww = canvas.winfo_width() # 獲取窗口寬度(update刷新之后才能獲取) def turn_left(event): canvas.move(id_paddle, -10, 0) def turn_right(event): canvas.move(id_paddle, 10, 0) def start_game(event): canvas.move(id_start_game,0,10) canvas.bind_all('<KeyPress-Left>', turn_left) canvas.bind_all('<KeyPress-Right>', turn_right) canvas.bind_all('<Button-1>', start_game) # 保持起始界面 while 1: tk.update() # 刷新窗口 p_start_game = canvas.coords(id_start_game) print(p_start_game) if p_start_game[1] == 210: canvas.delete(id_start_game) break # 讓球跑起來 while 1: tk.update() # 刷新窗口 time.sleep(0.01/level) # 通過level控制速度(也考慮過用球的顏色控制速度) p_ball = canvas.coords(id_ball) # 獲取球當前位置坐標 p_paddle = canvas.coords(id_paddle) # 獲取木板的坐標 print('當前坐標:',p_ball) # 打印當前坐標 if p_ball[0] <= 0: # 當球落到右邊框時:左上角x坐標判斷 x = 1 elif p_ball[2] >= ww: # 當球落到右邊框時,右下角x坐標判斷 x = -1 if p_ball[1] <= 0: # 當球落到上邊框時,左上角y坐標判斷 y = 1 elif p_ball[3] >= wh: # 當球落到下邊框時,右下角y坐標判斷 y = -1 print(p_ball[2],p_paddle[0],p_paddle[2],p_ball[3]) if p_ball[2]>=p_paddle[0] and p_ball[2]<=p_paddle[2] and p_ball[3] == p_paddle[1]: # 球與模板接觸:球的右下角x坐標在木板右上角x坐標內,且球的右下角x坐標在木板左下角x坐標內,球的右下角y坐標等於木板的左上角y坐標 y = -1 # 讓球向上移動 score += 10 # 得分加10分 canvas.itemconfig(id_ball, fill=random.choice(color_li)) # 修改球的顏色,隨機顏色 canvas.itemconfig(id_paddle, fill=random.choice(color_li)) # 修改木板的顏色,隨機顏色 canvas.itemconfig(id_score, text=score) # 修改分數 if score > 0 and score % 50 == 0: # 每50分升一級 level += 1 # 升級 canvas.itemconfig(id_level, text=level) # 修改等級 canvas.move(id_ball, x, y) # 移動 if p_ball[3] == wh: # 當球與下邊框接觸時,游戲失敗。 canvas.create_text(300, 250, text='Game Over !', font=('宋體', '30'), fill='red') # 添加游戲結束界面 break # 游戲結束,繼續保持界面 tk.mainloop()
最終執行效果:
知識點
1、導入模塊
import tkinter
2、生明一個tkinter實例(創建一個“窗口”)
tk = tkinter.Tk() # 聲明一個tkinter,初始化一個“窗口”(畫一個窗口)
3、設置窗口屬性
tk.title('彈球游戲') # 窗口名稱
tk.resizable(width=False,height=False) # 窗口是否可變(長、寬),也可用0,1表示
tk.wm_attributes('-topmost',1) # 窗口永遠在前
wm_attributes 可選屬性字段:
-topmost 是否是一個永遠最前的窗口
-alpha 窗口的透明度
-fullscreen 窗口是否滿屏顯示
-disabled 窗口是否是一個不可用的狀態(不能有任何操作)
4、組件實例
首先弄清楚坐標概念:
以畫布的左上角為原點(0,0)
以畫一個圓為例,需要通過“矩形”的左上角、右下角兩個坐標確定這個“矩形”的位置、大小,然后,在矩形中畫這個圓
tkinter.Canvas 創建畫布:

#!/user/bin env python # author:Simple-Sir # time:2020/8/3 17:12 import tkinter # 創建窗口 tk = tkinter.Tk() # 聲明一個TK,初始化一個“窗口”(畫一個窗口) tk.title('彈球游戲') # 窗口名稱 tk.resizable(width=False,height=False) # 窗口是否可變(長、寬),也可用0,1表示 tk.wm_attributes('-topmost',1) # 窗口永遠在前 canvas = tkinter.Canvas(tk,width=300,height=200,bd=0) # 創建一個“畫布” # width 寬 # height 高 # bd 邊框寬度(像素) # bg 背景顏色 # highlightthickness 顏色高亮 canvas.pack() # 將畫布添加到窗口中 tk.update() # 刷新窗口 # 進入消息循環 tk.mainloop() # 所有GUI程序都必須有一個主循環
執行結果:
畫布屬性:
move 移動
delete 刪除
winfo_height 獲取窗口高度(update刷新之后才能獲取)
winfo_width() 獲取窗口寬度(update刷新之后才能獲取)
coords 獲取目標當前坐標
itemconfig 修改組件屬性
畫布組件:
畫布組件屬性:
fill 填充顏色,默認不填充
stipple 位圖平鋪填充
outline 邊框顏色
width 邊框寬度,默認1
dash 邊框使用虛線。單獨整數:虛線線段長度 (n1,n2,n3):線段的長度n1,間隔長度n2,虛線長度n3
arrowshape 指定箭頭形狀。該選項是一個形如 "20 20 10" 的字符串,字符串中的三個整數依次指定填充長度、箭頭長度、箭頭寬度。
joinstyle 直線連接點的風格: miter、round、bevel
state 指定該畫布對象的狀態 NORMAL(正常,默認),DISABLED(不可用,不響應事件)和 HIDDEN(隱藏)
canvas.create_arc 創建扇形:

#!/user/bin env python # author:Simple-Sir # time:2020/8/3 17:12 import tkinter # 創建窗口 tk = tkinter.Tk() # 聲明一個TK,初始化一個“窗口”(畫一個窗口) tk.title('彈球游戲') # 窗口名稱 tk.resizable(width=False,height=False) # 窗口是否可變(長、寬),也可用0,1表示 tk.wm_attributes('-topmost',1) # 窗口永遠在前 # 創建畫布 canvas = tkinter.Canvas(tk,width=300,height=200,bd=0) # 創建一個“畫布” # width 寬 # height 高 # bd 邊框寬度(像素) # bg 背景顏色 # highlightthickness 顏色高亮 canvas.create_arc(0,0,100,100,start=0,extent=60,fill='red') # 指定坐標(左上、右下),開始度數,要畫的度數,填充顏色 # style PIESLICE - 扇形、CHORD - 弓形、ARC - 只畫一個弧) # start 扇形的起始角度,以3點鍾位置為0度,逆時針方向增加度數。 # extent 扇形要繪制的度數 canvas.pack() # 將畫布添加到窗口中 tk.update() # 刷新窗口 # 進入消息循環 tk.mainloop() # 所有GUI程序都必須有一個主循環
執行結果:
canvas.create_oval 創建圓:

#!/user/bin env python # author:Simple-Sir # time:2020/8/3 17:12 import tkinter # 創建窗口 tk = tkinter.Tk() # 聲明一個TK,初始化一個“窗口”(畫一個窗口) tk.title('彈球游戲') # 窗口名稱 tk.resizable(width=False,height=False) # 窗口是否可變(長、寬),也可用0,1表示 tk.wm_attributes('-topmost',1) # 窗口永遠在前 # 創建畫布 canvas = tkinter.Canvas(tk,width=300,height=200,bd=0) # 創建一個“畫布” # width 寬 # height 高 # bd 邊框寬度(像素) # bg 背景顏色 # highlightthickness 顏色高亮 # 創建圓 canvas.create_oval(10,10,100,100,fill='red') canvas.pack() # 將畫布添加到窗口中 tk.update() # 刷新窗口 # 進入消息循環 tk.mainloop() # 所有GUI程序都必須有一個主循環
執行結果:
canvascreate_image 創建圖像

#!/user/bin env python # author:Simple-Sir # time:2020/8/3 17:12 import tkinter # 創建窗口 tk = tkinter.Tk() # 聲明一個TK,初始化一個“窗口”(畫一個窗口) tk.title('彈球游戲') # 窗口名稱 tk.resizable(width=False,height=False) # 窗口是否可變(長、寬),也可用0,1表示 tk.wm_attributes('-topmost',1) # 窗口永遠在前 # 創建畫布 canvas = tkinter.Canvas(tk,width=300,height=200,bd=0) # 創建一個“畫布” # width 寬 # height 高 # bd 邊框寬度(像素) # bg 背景顏色 # highlightthickness 顏色高亮 # 創建圖像 filename = tkinter.PhotoImage(file="cat.png") canvas.create_image(10, 20, anchor='nw', image=filename) # 西距離邊框10,北距離邊框20 canvas.pack() # 將畫布添加到窗口中 tk.update() # 刷新窗口 # 進入消息循環 tk.mainloop() # 所有GUI程序都必須有一個主循環
執行結果:
canvas.create_line 創建線條

#!/user/bin env python # author:Simple-Sir # time:2020/8/3 17:12 import tkinter # 創建窗口 tk = tkinter.Tk() # 聲明一個TK,初始化一個“窗口”(畫一個窗口) tk.title('彈球游戲') # 窗口名稱 tk.resizable(width=False,height=False) # 窗口是否可變(長、寬),也可用0,1表示 tk.wm_attributes('-topmost',1) # 窗口永遠在前 # 創建畫布 canvas = tkinter.Canvas(tk,width=300,height=200,bd=0) # 創建一個“畫布” # width 寬 # height 高 # bd 邊框寬度(像素) # bg 背景顏色 # highlightthickness 顏色高亮 # line 線條 canvas.create_line(0,0,100,100,50,60,200,300,arrow='last',joinstyle='bevel') # 多個坐標會連續畫 # arrow 兩端是否有箭頭(none:兩端無箭頭、first:開始端有箭頭、last:結束端有箭頭、both:兩端都有箭頭。 canvas.pack() # 將畫布添加到窗口中 tk.update() # 刷新窗口 # 進入消息循環 tk.mainloop() # 所有GUI程序都必須有一個主循環
執行結果:

#!/user/bin env python # author:Simple-Sir # time:2020/8/3 17:12 import tkinter # 創建窗口 tk = tkinter.Tk() # 聲明一個TK,初始化一個“窗口”(畫一個窗口) tk.title('彈球游戲') # 窗口名稱 tk.resizable(width=False,height=False) # 窗口是否可變(長、寬),也可用0,1表示 tk.wm_attributes('-topmost',1) # 窗口永遠在前 # 創建畫布 canvas = tkinter.Canvas(tk,width=300,height=200,bd=0) # 創建一個“畫布” # width 寬 # height 高 # bd 邊框寬度(像素) # bg 背景顏色 # highlightthickness 顏色高亮 # rectangle 矩形 canvas.create_rectangle(0,10,100,150,fill='blue',outline='red',stipple='error',width=10,dash=(10,50,100)) # stipple 位圖平鋪填充 # outline 邊框顏色 # width 邊框寬度,默認1 # dash 邊框使用虛線。單獨整數:虛線線段長度 (n1,n2,n3):虛線線段長度n1,間隔長度n2,虛線長度n3 canvas.pack() # 將畫布添加到窗口中 tk.update() # 刷新窗口 # 進入消息循環 tk.mainloop() # 所有GUI程序都必須有一個主循環
執行結果:
創建多邊形:

#!/user/bin env python # author:Simple-Sir # time:2020/8/3 17:12 import tkinter # 創建窗口 tk = tkinter.Tk() # 聲明一個TK,初始化一個“窗口”(畫一個窗口) tk.title('彈球游戲') # 窗口名稱 tk.resizable(width=False,height=False) # 窗口是否可變(長、寬),也可用0,1表示 tk.wm_attributes('-topmost',1) # 窗口永遠在前 # 創建畫布 canvas = tkinter.Canvas(tk,width=300,height=200,bd=0) # 創建一個“畫布” # width 寬 # height 高 # bd 邊框寬度(像素) # bg 背景顏色 # highlightthickness 顏色高亮 # polygon 多邊形 canvas.create_polygon(0,0,100,200,100,250,50,300,fill='red',outline='red',stipple='error',width=10,dash=(10,50,100)) canvas.pack() # 將畫布添加到窗口中 tk.update() # 刷新窗口 # 進入消息循環 tk.mainloop() # 所有GUI程序都必須有一個主循環
執行結果:
創建文字:

#!/user/bin env python # author:Simple-Sir # time:2020/8/3 17:12 import tkinter # 創建窗口 tk = tkinter.Tk() # 聲明一個TK,初始化一個“窗口”(畫一個窗口) tk.title('彈球游戲') # 窗口名稱 tk.resizable(width=False,height=False) # 窗口是否可變(長、寬),也可用0,1表示 tk.wm_attributes('-topmost',1) # 窗口永遠在前 # 創建畫布 canvas = tkinter.Canvas(tk,width=300,height=200,bd=0) # 創建一個“畫布” # width 寬 # height 高 # bd 邊框寬度(像素) # bg 背景顏色 # highlightthickness 顏色高亮 canvas.create_text(100,100,text='使用text繪制文字',font='宋體',fill='red',anchor='n',justify='left',) # justify 文字的對齊方式:center、left、right canvas.pack() # 將畫布添加到窗口中 tk.update() # 刷新窗口 # 進入消息循環 tk.mainloop() # 所有GUI程序都必須有一個主循環
執行結果:
事件
三種綁定方式:
canvas.bind() # 綁定到某一個組件上
canvas.bind_all() # 綁定到所有組件上
canvas.bind_class() # 綁定到某一類組件上
鍵盤事件:
<Left>
<Right>
<Up>
<Down>
<BackSpace>
<Delete>
<Tab>
<Return>
<Shift_L>
<Shift_R>
<Control_L>
<Control_R>
<Alt_L>
<Alt_R>
<Home>
<Key> 或者 <KeyPress> 任意鍵盤按鍵
鼠標事件
<Button-1> 鼠標點擊(1-左鍵,2-中鍵,3-右鍵)
<Double-Button-1> 鼠標雙擊(1-左鍵,2-中鍵,3-右鍵)
<B1-Motion> 鼠標拖動(1-左鍵,2-中鍵,3-右鍵)
<ButtonRelease-1> 鼠標按下之后釋放(1-左鍵,2-中鍵,3-右鍵)
<Enter> 鼠標進入控件范圍
<Leave> 鼠標離開控件范圍