資源簡介 (共31張PPT)Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.少兒編程課王者榮耀英雄盒子本節我們來制作一個王者榮耀英雄盒子下面開始王者榮耀英雄盒子的制作1首先定義一個窗口,并設置窗口標題2運行效果如下from tkinter import *# 創建一個窗口root = Tk()# 限制窗口大小root.maxsize(995, 1025)root.minsize(995, 1025)# 窗口標題root.title('王者榮耀英雄選擇器')root.mainloop()然后在窗口中添加控件1定義“全部”按鈕,放到窗口中的第一行第一列2運行程序,結果如下:from tkinter import *# 創建一個窗口root = Tk()# 限制窗口大小root.maxsize(995, 1025)root.minsize(995, 1025)# 窗口標題root.title('王者榮耀英雄選擇器')# 全部all = Button(root, text='全部')all.grid(row=0, column=0, padx=30, pady=10)root.mainloop()練習Exercises密封線內不準答題將剩余的職業按鈕編寫出來,按鈕從左向右依次排列一起來看下如何做,定義及布局方式如下:1讓按鈕從左向右排列2運行效果如下:# 坦克is_tank = Button(root, text='坦克')is_tank.grid(row=0, column=1, padx=30, pady=10)# 戰士is_warrior = Button(root, text='戰士')is_warrior.grid(row=0, column=2, padx=30, pady=10)# 刺客is_assa = Button(root, text='刺客')is_assa.grid(row=0, column=3, padx=30, pady=10)# 法師is_master = Button(root, text='法師')is_master.grid(row=0, column=4, padx=30, pady=10)# 射手is_archer = Button(root, text='射手')is_archer.grid(row=0, column=5, padx=30, pady=10)# 輔助is_sup = Button(root, text='輔助')is_sup.grid(row=0, column=6, padx=30, pady=10)注意:grid布局時行號和列號依次為(0,1)、(0,2)、(0,3)、(0,4)、(0,5)、(0,6)接下來我們加入模糊查詢相關的控件:所謂“模糊查詢”是指,當你想要查詢某件事物時不需要輸入非常精確地信息,即使是輸入這個事物的一部分信息,也可以查詢出來。1創建輸入框和按鈕并加入到窗口中運行程序,看下效果2下面實現模糊查詢的界面效果# 創建輸入框entry = Entry(root)entry.grid(row=0, column=7, padx=20)# 確定按鈕commit = Button(root, text='確定')commit.grid(row=0, column=8)英雄信息顯示接下來,我們為按鈕添加功能,讓其能夠在被點擊之后,使窗口顯示圖片和英雄名首先將已經準備好的英雄信息表,復制過來12hero_info_list = [{'index_num': 1, 'name': '米萊狄', 'img_path': ".\\hero_img\\米萊狄.jpg", 'is_tank': 0, 'is_warrior': 0, 'is_assa': 0,'is_master': 1, 'is_archer': 0, 'is_sup': 0},{'index_num': 2, 'name': '狂鐵', 'img_path': ".\\hero_img\\狂鐵.jpg", 'is_tank': 0, 'is_warrior': 1, 'is_assa': 0,...{'index_num': 80, 'name': '廉頗', 'img_path': ".\\hero_img\\廉頗.jpg", 'is_tank': 1, 'is_warrior': 0, 'is_assa': 0,'is_master': 0, 'is_archer': 0, 'is_sup': 0}]然后再將英雄圖片文件夾復制到項目文件夾下3導入Pillow中的Image、ImageTkfrom PIL import Imagefrom PIL import ImageTk4創建一個Frame,用于放置英雄圖片和姓名標簽Frame# 創建一個Frame控件,用于布局圖片和英雄名frame = Frame(root)frame.grid(row=1, column=0, columnspan=10, sticky=W)這里的stickey屬性可以設置控件的排列方式,‘W’表示從最左側開始排列。界面已經開發完成,接下來我們將功能實現def all_callback():row_num = 0col_num = 0for i in hero_info_list:# 處理圖片img= Image.open(i.get('img_path'))img= ImageTk.PhotoImage(img)# 動態生成不同變量名的Label標簽label_img = Label(frame, width=95, height=95, image=img)label_name = Label(frame, text=i.get('name'))首先定義回調函數,處理圖片并生成標簽12然后使用Grid布局,布局方式如下圖:這里的行號和列號應該怎么寫呢,先來看行號2104680英雄圖片的行號每十個變化一次都是0246810...這種偶數使用一個從0開始每次自增1的數整除10之后在乘2就可以表示( 2 * (row_num // 10) )英雄名在圖片下方,行號每次都比行號多1,所以可以用( 2 * (row_num // 10) + 1 )表示然后再看下列號的規律:0123456987列號自始至終都是從0到9,可以這樣去表示:讓一個為0的數,每一次遍歷都增加1,當這個數等于10時,我們將它的值重新設為0最后,我們將回調函數補充完整:按照我們驗證好的布局方式,將回調函數補充完整def all_callback():row_num = 0col_num = 0for i in hero_info_list:# 處理圖片img= Image.open(i.get('img_path'))img= ImageTk.PhotoImage(img)# 動態生成不同變量名的Label標簽label_img = Label(frame, width=95, height=95, image=img)label_name = Label(frame, text=i.get('name'))# 將生成的標簽進行布局# 0 2 4 6 8 10label_img.grid(row=2 * (row_num // 10), column=col_num)# 1 3 5 7 9label_name.grid(row=2 * (row_num // 10) + 1, column=col_num)row_num += 1col_num += 1# 如果列號為10時,重新設為0if col_num == 10:col_num = 0# 重新進入循環root.mainloop()1將回調函數綁定到全部按鈕中# 全部all = Button(root, text='全部', command=all_callback)all.grid(row=0, column=0, padx=30, pady=10)2完善全部按鈕的回調函數,運行效果如下:為什么圖片沒有顯示呢???來看一下圖片為什么沒有顯示出來img1img1圖片處理使用pillow處理圖片時,當圖片處理程序處理完一張圖片之后,馬上處理下一張圖片由于我們使用的是同一個變量名,所以后一張圖片會將前面的覆蓋掉,所以圖片會顯示不出來。如何解決這個問題呢?解決英雄圖片顯示不出來的bug12再次運行程序,點擊全部按鈕,問題被解決。使用locals()[‘img’ + str(row_num)]動態生成變量名,修改代碼。# 處理圖片locals()['img' + str(row_num)] = Image.open(i.get('img_path'))locals()['img' + str(row_num)] = ImageTk.PhotoImage(locals()['img' + str(row_num)])# 動態生成不同變量名的Label標簽label_img = Label(frame, width=95, height=95, image=locals()['img' + str(row_num)])現在繼續為第二個按鈕,坦克按鈕添加功能12坦克按鈕添加回調函數之后,運行程序。直接復制全部按鈕的代碼,添加一個判斷即可。def tank_callback():row_num = 0col_num = 0for i in hero_info_list:if i.get('is_tank'):# 處理圖片locals()['img' + str(i)] = Image.open(i.get('img_path'))locals()['img' + str(i)] = ImageTk.PhotoImage(locals()['img' + str(i)])# 動態生成不同變量名的Label標簽label_img = Label(frame, width=95, height=95, image=locals()['img' + str(i)])label_name = Label(frame, text=i.get('name'))# 將生成的標簽進行布局label_img.grid(row=2 * (row_num // 10), column=col_num) # 0 2 4 6 8label_name.grid(row=2 * (row_num // 10) + 1, column=col_num) # 1 3 5 6 7 9row_num += 1col_num += 1# 如果列號為10時,重新設為0if col_num == 10:col_num = 0# 重新進入事件循環root.mainloop()這里復制之后,注意代碼的縮進問題。如何避免重復性工作?我們可以通過相同的方式去實現其他幾個職業按鈕的功能def tank_callback():row_num = 0col_num = 0for i in hero_info_list:if i.get('is_warrior'):# 處理圖片locals()['img' + str(i)] = Image.open(i.get('img_path'))locals()['img' + str(i)] = ImageTk.PhotoImage(locals()['img' + str(i)])# 動態生成不同變量名的Label標簽label_img = Label(frame, width=95, height=95, image=locals()['img' + str(i)])label_name = Label(frame, text=i.get('name'))# 將生成的標簽進行布局label_img.grid(row=2 * (row_num // 10), column=col_num) # 0 2 4 6 8label_name.grid(row=2 * (row_num // 10) + 1, column=col_num) # 1 3 5 6 7 9row_num += 1col_num += 1# 如果列號為10時,重新設為0if col_num == 10:col_num = 0# 重新進入事件循環root.mainloop()def tank_callback():row_num = 0col_num = 0for i in hero_info_list:if i.get('is_assa'):# 處理圖片locals()['img' + str(i)] = Image.open(i.get('img_path'))locals()['img' + str(i)] = ImageTk.PhotoImage(locals()['img' + str(i)])# 動態生成不同變量名的Label標簽label_img = Label(frame, width=95, height=95, image=locals()['img' + str(i)])label_name = Label(frame, text=i.get('name'))# 將生成的標簽進行布局label_img.grid(row=2 * (row_num // 10), column=col_num) # 0 2 4 6 8label_name.grid(row=2 * (row_num // 10) + 1, column=col_num) # 1 3 5 6 7 9row_num += 1col_num += 1# 如果列號為10時,重新設為0if col_num == 10:col_num = 0# 重新進入事件循環root.mainloop()def tank_callback():row_num = 0col_num = 0for i in hero_info_list:if i.get(‘is_master’):# 處理圖片。。。root.mainloop()def tank_callback():row_num = 0col_num = 0for i in hero_info_list:if i.get('is_archer'):# 處理圖片。。。root.mainloop()戰士刺客法師射手四段代碼唯一不同的地方如何避免這種重復工作呢 程序結構與代碼的優化現在為止,基本的功能已經全部實現,下面來理清程序邏輯整體邏輯如下圖:可以發現,在我們將界面編寫完成之后,所需要做的只是為按鈕添加回調函數編寫界面,可點擊的按鈕及輸入框為按鈕添加回調函數獲得符合條件的英雄信息表處理信息表中的圖片,生成向應標簽然后布局將回調函數綁定到對應的職業按鈕而在回調函數中,所進行的主要操作也只是分為兩步:獲得正確的信息表和處理圖片布局展示所以我們可以嘗試來優化代碼優化思路如下:定義兩個根據不同的情況返回不同英雄信息表的函數定義統一圖片處理、生成標簽并布局的函數點擊職業按鈕時,根據傳入的職業參數返回相應職業英雄信息表的函數點擊確定按鈕時,根據輸入返回相應英雄信息表的函數定義主函數,作為所有按鈕的回調函數,根據不同的情況,調用不同的函數函數一函數二如果我們點擊的是職業按鈕,那么調用函數一和布局函數如果我們點擊的是職業按鈕,那么調用函數二和布局函數情況一情況二現在按照上面的步驟,編寫代碼。首先定義一個點擊職業按鈕后,根據不同參數,返回不同職業的英雄信息列表的函數def get_hero_list_by_career(career):# 當點擊按鈕全部時,直接返回全部的英雄信息列表if career == 'all':return hero_info_list# 根據傳入的職業名字篩選else:# 并新建英雄信息列表hero_select_list = []for i in hero_info_list:# 判斷每一個獲取到的英雄是否是這個職業if i.get(career):# 將符合條件的添加到新列表中hero_select_list.append(i)# 將新的英雄信息列表返回return hero_select_list在編寫一個點擊確定按鈕后,根據輸入框中的內容返回英雄信息表的函數def get_hero_list_by_input(entry_text):hero_list_select = []# 輸入框有內容時,根據輸入的內容進行模糊查詢if entry_text:for i in hero_info_list:# 判斷英雄名中是否包含輸入的字符if i.get('name').find(entry_text) != -1:# 符合條件的添加到新列表中hero_list_select.append(i)# 將新的英雄信息列表返回return hero_list_select# 若輸入框沒有內容且確認按鈕被點擊,直接返回else:return接著定義一個統一的圖片處理、生成標簽并布局的函數def widget_create(select_hero_list):# 刪除原來的控件for widget in frame.winfo_children():widget.destroy()row_num = 0col_num = 0# 如果能夠獲取到英雄信息列表時才開始進行處理if select_hero_list:for i in select_hero_list:# 將每一個圖片處理成標簽可以接受的類型locals()['img' + str(col_num)] = Image.open(i.get('img_path'))locals()['img' + str(col_num)] = ImageTk.PhotoImage(locals()['img' + str(col_num)])# 創建Label標簽,分別顯示圖片和文字label_img = Label(frame, width=95, height=95, image=locals()['img' + str(col_num)])label_name = Label(frame, text=i.get('name'))# 將創建好的Label標簽進行布局label_img.grid(row=2 * (row_num // 10), column=col_num) # 0 2 4 6 8 10label_name.grid(row=2 * (row_num // 10) + 1, column=col_num) # 1 3 5 7 9# 累加row_num += 1col_num += 1# 每當col_num等于10,將它的值重新設為0,保證每一行只顯示十個英雄if col_num == 10:col_num = 0# 重新進入事件循環root.mainloop()注意:這里的圖片處理部分的代碼和之前是一樣的,可以復制一段過來,然后只添加黃色部分。上面三個函數編寫完成之后,再去定義一個主回調函數def display_hero(career):# 當被點擊按鈕為確定按鈕且輸入框輸入了內容,調用獲取英雄列表和創建部件方法if career == 'commit':if entry.get():# 調用根據輸入獲取列表函數hero_list = get_hero_list_by_input(entry.get())# 調用處理圖片生成標簽并布局展示函數widget_create(hero_list)else:# 如果被點擊按鈕不是確定按鈕,則調用根據職業獲取英雄列表函數hero_list = get_hero_list_by_career(career)widget_create(hero_list)最后,我們修改按鈕的回調函數屬性為所有按鈕設置回調函數并傳參在這里,我們借助了lambda表達式的幫忙,用于傳遞參數,如果不使用這種方式直接傳參,程序將會報錯。all = Button(root, text='全部', command=lambda: display_hero('all'))is_tank = Button(root, text='坦克', command=lambda: display_hero('is_tank'))is_warrior = Button(root, text='戰士', command=lambda: display_hero('is_warrior'))is_assa = Button(root, text='刺客', command=lambda: display_hero('is_assa'))is_master = Button(root, text='法師', command=lambda: display_hero('is_master'))is_archer = Button(root, text='射手', command=lambda: display_hero('is_archer'))is_sup = Button(root, text='輔助', command=lambda: display_hero('is_sup'))commit = Button(root, text='確定', command=lambda: display_hero('commit'))現在,我們的王者榮耀英雄盒子就制作完成了運行程序,點擊不同的按鈕,查看一下效果:總結Summarytkinter中按鈕、輸入框、標簽等控件的使用√第三方庫Pillow使用√Thanks! 展開更多...... 收起↑ 資源預覽 縮略圖、資源來源于二一教育資源庫