北京注冊網(wǎng)站廣州建設(shè)工程造價管理站網(wǎng)站
鶴壁市浩天電氣有限公司
2026/01/24 14:22:00
北京注冊網(wǎng)站,廣州建設(shè)工程造價管理站網(wǎng)站,仿站酷網(wǎng)站模板,研究生網(wǎng)站建設(shè)大哥大飯店點餐系統(tǒng)**——Python Tkinter 桌面點餐管理系統(tǒng)#xff08;完整源碼分享#xff09;** 項目簡介#xff1a;一個基于 Python Tkinter 的輕量級桌面點餐系統(tǒng)#xff0c;適合中小型飯店使用。實現(xiàn)了顧客點餐#xff08;支持辣度、備注#xff09;、管理員登錄、…大哥大飯店點餐系統(tǒng)**——Python Tkinter 桌面點餐管理系統(tǒng)完整源碼分享**項目簡介一個基于 Python Tkinter 的輕量級桌面點餐系統(tǒng)適合中小型飯店使用。實現(xiàn)了顧客點餐支持辣度、備注、管理員登錄、菜品管理、訂單持久化、營業(yè)數(shù)據(jù)統(tǒng)計與 Matplotlib 可視化展示。全程使用 JSON 文件存儲數(shù)據(jù)無需數(shù)據(jù)庫純本地運行開箱即用。技術(shù)棧Python 3.x、Tkinter、JSON、Matplotlib開發(fā)日期2025年12月作者kblj5555前言在學(xué)習(xí) Python 編程的過程中學(xué)校的課程設(shè)計要求我們做一個GUI項目因為家里是開飯店的所以我想做一個貼近自己家庭生活的實戰(zhàn)項目先用簡單的做一個整體構(gòu)思框架等并在以后有機會的情況下做一個能用于自己家的小項目。于是我決定開發(fā)一個簡單實用的大哥大飯店點餐系統(tǒng)。本系統(tǒng)完全使用 Python 標(biāo)準(zhǔn)庫 Tkinter 實現(xiàn)界面數(shù)據(jù)用 JSON 文件持久化統(tǒng)計模塊嵌入 Matplotlib 實現(xiàn)圖表可視化。整個項目只有 4 個核心 py 文件 3 個 JSON 數(shù)據(jù)文件結(jié)構(gòu)清晰易于二次開發(fā)。本系統(tǒng)開發(fā)階段由于時間緊張所以無法展現(xiàn)完整功能的作品且大量借助了AI的力量所以后續(xù)代碼的結(jié)構(gòu)不是很完整且若大家代碼有什么看不懂的且沒有注釋希望大家借助AI來幫助自己在這里感謝Tare CN、Gork、豆包對我的幫助。主要功能顧客桌號選擇、瀏覽菜品、雙擊點餐可選辣度 備注、訂單管理、確認(rèn)下單管理員登錄驗證、創(chuàng)建管理員賬號、菜品管理框架、查看訂單、營業(yè)額統(tǒng)計按天/按星期 圖表數(shù)據(jù)持久化菜單、用戶信息、營業(yè)數(shù)據(jù)全部本地保存重啟不丟失下面分享整個開發(fā)思路、實現(xiàn)過程和完整源碼希望對正在學(xué)習(xí) Tkinter 的同學(xué)有所幫助整體規(guī)劃項目結(jié)構(gòu)text大哥大飯店點餐系統(tǒng)/ ├── main.py # 程序入口、主界面、桌號選擇、管理者登錄 ├── order.py # 顧客點餐核心模塊 ├── guanli.py # 管理員管理模塊菜品管理、統(tǒng)計入口 ├── shuju.py # 營業(yè)數(shù)據(jù)統(tǒng)計與圖表可視化 ├── 用戶信息.json # 管理員賬號密碼默認(rèn)有幾個測試賬號 ├── 菜單.json # 菜品信息19道菜示例 ├── 營業(yè)數(shù)據(jù).json # 歷史訂單記錄 └── README.md # 項目說明就是本文模塊職責(zé)劃分main.py系統(tǒng)啟動、歡迎界面、1-9桌選擇、管理者登錄跳轉(zhuǎn)order.py點餐主邏輯雙擊點餐、辣度備注、訂單增刪、確認(rèn)下單并保存guanli.py管理員界面框架菜品管理基礎(chǔ)功能跳轉(zhuǎn)統(tǒng)計shuju.py獨立統(tǒng)計窗口按天每小時折線圖/按星期每天柱狀圖支持中文顯示數(shù)據(jù)存儲設(shè)計全部使用 JSON 文件無需額外安裝數(shù)據(jù)庫用戶信息.json存儲管理員賬號、密碼、角色菜單.json菜品列表id、name、price、category營業(yè)數(shù)據(jù).json訂單數(shù)組訂單編號、時間、桌號、菜品詳情、總金額具體實現(xiàn)1. 主入口與桌號選擇main.py使用九宮格按鈕實現(xiàn)1-9桌選擇點擊后銷毀主窗口并傳入桌號打開點餐界面。同時提供“管理者登錄”入口支持創(chuàng)建新管理員賬號。2. 顧客點餐order.py雙擊菜品彈出辣度清淡/微辣/中辣/爆辣和備注輸入框右側(cè)實時顯示已選菜品支持刪除總金額自動計算確認(rèn)下單后生成唯一訂單編號追加寫入 營業(yè)數(shù)據(jù).json3. 管理員管理guanli.py根據(jù)顧客點餐order.py基礎(chǔ)框架擴展完整菜品增刪改查兩者基本上是相同的減少桌號功能??商D(zhuǎn)到統(tǒng)計界面。4. 營業(yè)數(shù)據(jù)統(tǒng)計shuju.py讀取所有歷史訂單支持“按天”查看24小時銷售額折線圖支持“按星期”查看7天銷售額柱狀圖使用 FigureCanvasTkAgg 將 Matplotlib 圖表嵌入 Tkinter 窗口支持中文顯示SimHei 字體加分點辣度和備注自定義Matplotlib 完美嵌入 Tkinter相對路徑統(tǒng)一項目可直接復(fù)制運行管理員賬號動態(tài)創(chuàng)建完整代碼1. main.py程序入口Pythonimporttkinterastfromtkinterimportmessageboxasinfoimportjson,osimportguanli,order currentdiros.path.dirname(os.path.abspath(__file__))USER_INFO_FILEos.path.join(currentdir,用戶信息.json)# 讀取用戶信息defread_user_info():從JSON文件中讀取用戶信息列表try:withopen(USER_INFO_FILE,r,encodingutf-8)asfile:returnjson.load(file)exceptFileNotFoundError:info.showerror(錯誤,用戶信息文件未找到)return[]# 保存用戶信息defsave_user_info(user_info_list):將用戶信息列表保存到JSON文件中try:withopen(USER_INFO_FILE,w,encodingutf-8)asfile:json.dump(user_info_list,file,ensure_asciiFalse,indent4)returnTrueexceptExceptionase:info.showerror(錯誤,f保存用戶信息失敗:{str(e)})returnFalse# 登錄驗證defvalidate_login(username,password):驗證用戶名和密碼是否正確 Args: username: 用戶名 password: 密碼 Returns: 驗證成功返回用戶信息字典失敗返回None user_info_listread_user_info()foruserinuser_info_list:ifuser[賬號]usernameanduser[密碼]password:returnuserreturnNone# 打開訂單系統(tǒng)defopen_order(desk_number):打開訂單系統(tǒng) Args: desk_number: 桌號 try:# 直接調(diào)用order模塊的create_order_window函數(shù)order.create_order_window(str(desk_number))exceptExceptionase:info.showerror(錯誤,f打開訂單系統(tǒng)失敗:{str(e)})# 管理者登錄窗口defmanager_login_window():打開管理者登錄窗口deflogin():處理登錄按鈕點擊事件usernameusername_entry.get()passwordpassword_entry.get()uservalidate_login(username,password)ifuseranduser[角色]管理者:login_window.destroy()open_manager_menu()else:info.showerror(錯誤,賬號或密碼錯誤或無管理者權(quán)限)defback_to_main():返回主界面login_window.destroy()main_window()# 返回主界面login_windowt.Tk()login_window.title(管理者登錄)login_window.geometry(400x300)# 增大窗口大小login_window.resizable(False,False)t.Label(login_window,text管理者登錄,font(宋體,14)).pack(pady10)t.Label(login_window,text賬號:).pack(pady5)username_entryt.Entry(login_window)# 賬號輸入框username_entry.pack()t.Label(login_window,text密碼:).pack(pady5)password_entryt.Entry(login_window,show*)# 密碼輸入框密碼以*顯示password_entry.pack()button_framet.Frame(login_window)# 創(chuàng)建按鈕框架button_frame.pack(pady20)t.Button(button_frame,text登錄,commandlogin,width15).pack(sideleft,padx10)t.Button(button_frame,text返回主界面,commandback_to_main,width15).pack(sideleft,padx10)# 管理者菜單defopen_manager_menu():打開管理者菜單窗口defcreate_new_account():創(chuàng)建新管理者賬號defsave_new_account():保存新賬號new_usernamenew_username_entry.get()new_passwordnew_password_entry.get()new_role管理者ifnotnew_usernameornotnew_password:info.showwarning(警告,賬號和密碼不能為空)returnuser_info_listread_user_info()# 檢查賬號是否已存在foruserinuser_info_list:ifuser[賬號]new_username:info.showwarning(警告,賬號已存在)return# 添加新賬號new_user{賬號:new_username,密碼:new_password,角色:new_role}user_info_list.append(new_user)ifsave_user_info(user_info_list):info.showinfo(成功,新賬號創(chuàng)建成功)account_window.destroy()manager_window.destroy()main_window()# 創(chuàng)建成功后返回主界面defback_to_manager_menu():返回管理者菜單account_window.destroy()account_windowt.Toplevel()account_window.title(創(chuàng)建新賬號)account_window.geometry(300x250)account_window.resizable(False,False)t.Label(account_window,text創(chuàng)建管理者賬號,font(宋體,14)).pack(pady10)t.Label(account_window,text新賬號:).pack(pady5)new_username_entryt.Entry(account_window)# 新賬號輸入框new_username_entry.pack()t.Label(account_window,text新密碼:).pack(pady5)new_password_entryt.Entry(account_window,show*)# 新密碼輸入框new_password_entry.pack()button_framet.Frame(account_window)# 按鈕框架button_frame.pack(pady20)t.Button(button_frame,text創(chuàng)建,commandsave_new_account,width12).pack(sideleft,padx5)t.Button(button_frame,text返回,commandback_to_manager_menu,width12).pack(sideleft,padx5)defopen_management_system():打開管理系統(tǒng)try:manager_window.destroy()# 直接調(diào)用guanli模塊的create_guanli_window函數(shù)guanli.create_guanli_window()exceptExceptionase:info.showerror(錯誤,f打開管理系統(tǒng)失敗:{str(e)})defback_to_main():返回主界面manager_window.destroy()main_window()# 返回主界面manager_windowt.Tk()manager_window.title(管理者菜單)manager_window.geometry(400x300)manager_window.resizable(False,False)t.Label(manager_window,text管理者菜單,font(宋體,16)).pack(pady20)t.Button(manager_window,text創(chuàng)建新管理者賬號,commandcreate_new_account,width20,height2).pack(pady10)t.Button(manager_window,text打開管理系統(tǒng),commandopen_management_system,width20,height2).pack(pady10)t.Button(manager_window,text返回主界面,commandback_to_main,width20,height2).pack(pady10)# 主界面defmain_window():打開系統(tǒng)主界面windowt.Tk()window.title(大哥大飯店 - 登錄系統(tǒng))window.geometry(1000x800)window.resizable(False,False)# 歡迎語t.Label(window,text歡迎來到大哥大飯店,font(宋體,24),fgred).pack(pady30)# 桌號按鈕區(qū)域t.Label(window,text請選擇桌號,font(宋體,16)).pack(pady10)# 九宮格按鈕布局button_framet.Frame(window)# 創(chuàng)建按鈕框架button_frame.pack(pady20)# 創(chuàng)建1-9的桌號按鈕foriinrange(1,10):row(i-1)//3# 計算按鈕所在行0-2col(i-1)%3# 計算按鈕所在列0-2# 創(chuàng)建桌號按鈕點擊后關(guān)閉當(dāng)前窗口并打開點餐系統(tǒng)同時傳遞桌號參數(shù)btnt.Button(button_frame,textstr(i),width15,height5,font(宋體,14),commandlambdanumi:[window.destroy(),open_order(num)])btn.grid(rowrow,columncol,padx15,pady15)# 設(shè)置按鈕位置和間距# 管理者登錄按鈕manager_btnt.Button(window,text管理者登錄,commandlambda:[window.destroy(),manager_login_window()],width20,height2,font(宋體,12))manager_btn.pack(pady15)# 減小pady值確保按鈕可見window.mainloop()# 啟動主界面循環(huán)# 啟動程序if__name____main__:main_window()# 啟動程序主界面2. order.py顧客點餐核心Pythonimporttkinterastfromtkinterimportmessageboxasinfoimportjsonimportos,datetime,subprocess,sysimportmain,shuju# 基本初始數(shù)據(jù)# 訂單信息ordered_items[]total_price0.0current_desk_number未知桌號# 當(dāng)前桌號默認(rèn)為未知桌號# 初始化桌號函數(shù)definit_desk_number():從命令行參數(shù)獲取并初始化桌號globalcurrent_desk_numberimportsysiflen(sys.argv)1:current_desk_numbersys.argv[1]# 類集合# 辣度類classLadu:def__init__(self,name):self.namenamedef__str__(self):returnself.name# 菜單類classDish:def__init__(self,name,price,category熱菜,laduLadu(微辣),beizhu無):self.namename self.priceprice self.categorycategory self.laduladu self.beizhubeizhu# 菜單顯示格式和__init__同級縮進defdisplay_in_menu(self):returnf{self.name}-{self.price}元 -{self.category}# 菜品字符串表示用于已選列表顯示def__str__(self):returnf{self.name}-{self.ladu}- 備注{self.beizhu}-{self.price}元# 菜品庫menu_items{}# 函數(shù)集合# 保存菜單函數(shù)defsave_menu_to_json():# 保存內(nèi)容到菜單文件globalmenu json_filer./菜單.jsontry:menu_data[]fora,(dish_name,dish_object)inenumerate(menu_items.items(),1):menu_data.append({id:a,name:dish_object.name,price:dish_object.price,category:dish_object.category})withopen(json_file,w,encodingutf-8)asfile:json.dump(menu_data,file,ensure_asciiFalse,indent4)print(f保存了{(lán)len(menu_data)}菜品)exceptExceptionase:print(f保存失敗原因為{str(e)})# 保存營業(yè)額函數(shù)defsave_sales_data():將當(dāng)前訂單保存為營業(yè)數(shù)據(jù)到JSON文件globalordered_items,total_price sales_file_pathr./營業(yè)數(shù)據(jù).jsontry:# 獲取當(dāng)前時間nowdatetime.datetime.now()current_datenow.strftime(%Y%m%d)# YYYYMMDD格式的日期current_timenow.strftime(%Y-%m-%d %H:%M:%S)# 完整時間格式# 讀取現(xiàn)有營業(yè)數(shù)據(jù)sales_data[]ifos.path.exists(sales_file_path):try:withopen(sales_file_path,r,encodingutf-8)asfile:file_contentfile.read().strip()iffile_content:sales_datajson.loads(file_content)exceptjson.JSONDecodeError:# 文件內(nèi)容不是有效的JSON創(chuàng)建一個新的空列表sales_data[]# 生成訂單編號當(dāng)天時間編號today_orders0fororderinsales_data:if訂單編號inorderandorder[訂單編號].startswith(current_date):today_orders1order_numberf{current_date}{today_orders1:03d}# 生成訂單編號# 準(zhǔn)備訂單詳情order_details[]fordishinordered_items:order_details.append({菜品名:dish.name,辣度:str(dish.ladu),備注:dish.beizhu,價格:dish.price})# 創(chuàng)建新訂單數(shù)據(jù)new_order{訂單編號:order_number,時間:current_time,桌號:current_desk_number,# 使用當(dāng)前桌號具體內(nèi)容:order_details,總金額:total_price}# 添加新訂單到營業(yè)數(shù)據(jù)sales_data.append(new_order)# 保存更新后的營業(yè)數(shù)據(jù)確保使用UTF-8編碼withopen(sales_file_path,w,encodingutf-8,newline)asfile:json.dump(sales_data,file,ensure_asciiFalse,indent4,defaultstr)print(f營業(yè)數(shù)據(jù)保存成功{order_number})exceptExceptionase:print(f保存營業(yè)數(shù)據(jù)失敗{str(e)})info.showerror(錯誤,f保存營業(yè)數(shù)據(jù)失敗{str(e)})# 清空當(dāng)前訂單函數(shù)defclear_current_order():清空當(dāng)前訂單的所有菜品和總價globalordered_items,total_price ordered_items[]# 清空已點菜品列表total_price0.0# 清空總價selected_listbox.delete(0,end)# 清空列表框顯示# 讀取菜單函數(shù)defmenu():# 從json文件加載菜單數(shù)據(jù)并傳喚為菜單globalmenu_items json_pathr./菜單.jsontry:withopen(json_path,r,encodingutf-8)asfile:menu_datajson.load(file)# 將json數(shù)據(jù)轉(zhuǎn)換為dish對象字典menu_items{}foriteminmenu_data:dish_nameitem[name]dish_priceitem[price]dish_categoryitem.get(category,熱菜)menu_items[dish_name]Dish(dish_name,dish_price,dish_category)print(f共打印了{(lán)len(menu_items)}個菜品)exceptFileNotFoundError:print(fJSON文件{json}為找到)# 備用方案menu_items{麻辣香鍋:Dish(麻辣香鍋,58,熱菜),水煮魚:Dish(水煮魚,88,熱菜),回鍋肉:Dish(回鍋肉,42,熱菜),番茄炒蛋:Dish(番茄炒蛋,22,熱菜),魚香肉絲:Dish(魚香肉絲,38,熱菜),}save_menu_to_json()# 加菜函數(shù)defadd_dish(dish_object):加菜函數(shù)說明 點擊下單后彈出備注窗口 功能如下 辣度選擇 備注 取消下單 彈出辣度選擇窗口讓用戶選擇菜品的辣度和備注# 創(chuàng)建新的辣度選擇窗口beizhu_windowt.Toplevel()beizhu_window.title(f選擇{dish_object.name}的辣度)beizhu_window.geometry(300x250)# 固定窗口大小# 辣度選擇單選按鈕ladu_vart.StringVar(value微辣)# 默認(rèn)微辣t.Label(beizhu_window,text選擇辣度).pack(pady5)t.Radiobutton(beizhu_window,text清淡,variableladu_var,value清淡).pack()t.Radiobutton(beizhu_window,text微辣,variableladu_var,value微辣).pack()t.Radiobutton(beizhu_window,text中辣,variableladu_var,value中辣).pack()t.Radiobutton(beizhu_window,text爆辣,variableladu_var,value爆辣).pack()# 備注輸入框t.Label(beizhu_window,text備注忌口等).pack(pady5)beizhu_vart.StringVar(value無)# 默認(rèn)無備注beizhu_entryt.Entry(beizhu_window,textvariablebeizhu_var)beizhu_entry.pack()# 確認(rèn)添加按鈕函數(shù)defxiadan():確認(rèn)添加菜品到訂單selected_ladu_nameladu_var.get()# 獲取選擇的辣度名稱selected_beizhubeizhu_var.get()# 獲取備注# 創(chuàng)建辣度對象selected_laduLadu(selected_ladu_name)# 創(chuàng)建新的菜品對象包含用戶選擇的辣度和備注selected_dishDish(dish_object.name,dish_object.price,dish_object.category,selected_ladu,selected_beizhu)# 將菜品對象添加到訂單ordered_items.append(selected_dish)globaltotal_price# 聲明使用全局變量total_pricedish_object.price# 更新總價# 更新右側(cè)已選菜品列表selected_listbox.insert(end,str(selected_dish))# 關(guān)閉辣度選擇窗口beizhu_window.destroy()# 顯示成功信息info.showinfo(提示,f{dish_object.name}已加入訂單)# 返回主界面函數(shù)defback():返回主界面不添加菜品beizhu_window.destroy()# 創(chuàng)建按鈕容器button_framet.Frame(beizhu_window)button_frame.pack(pady10)# 添加按鈕t.Button(button_frame,text確認(rèn)添加,commandxiadan).pack(sideleft,padx5)t.Button(button_frame,text返回,commandback).pack(sideleft,padx5)# 刪菜函數(shù)defdelete_dish():刪除選中的已點菜品# 獲取選中菜品的索引selected_indexselected_listbox.curselection()ifnotselected_index:# 如果沒有選中任何菜品則顯示提示info.showwarning(提示,先選中要刪除的菜品)returnindexselected_index[0]# 從訂單中刪除菜品對象并更新總價deleted_dishordered_items.pop(index)globaltotal_price total_price-deleted_dish.price# 更新總價# 從列表框顯示中刪除selected_listbox.delete(index)info.showinfo(提示,f已刪除{deleted_dish.name})# 預(yù)覽菜單函數(shù)defview_preview():顯示當(dāng)前訂單的預(yù)覽信息ifnotordered_items:# 如果沒有點任何菜品則顯示提示info.showwarning(提示,還沒點任何菜品)return# 組裝預(yù)覽內(nèi)容preview_content 訂單預(yù)覽
fornumber,dish_objectinenumerate(ordered_items,1):preview_contentf{number}.{dish_object.name}-{dish_object.ladu}- 備注{dish_object.beizhu}-{dish_object.price}元
preview_contentf
總價{total_price}元# 顯示彈窗info.showinfo(訂單預(yù)覽,preview_content)# 下單函數(shù)defxiadan_dish():確認(rèn)當(dāng)前訂單并保存營業(yè)數(shù)據(jù)ifnotordered_items:info.showwarning(提示,沒點菜品不能下單)return# 組裝訂單信息order_content 下單成功
fornumber,dish_objectinenumerate(ordered_items,1):order_contentf{number}.{dish_object.name}-{dish_object.ladu}- 備注{dish_object.beizhu}-{dish_object.price}元
order_contentf
總價{total_price}元
坐等上菜info.showinfo(下單成功,order_content)# 保存營業(yè)數(shù)據(jù)到JSON文件save_sales_data()# 清空當(dāng)前訂單clear_current_order()# 用戶/加菜功能函數(shù)集合調(diào)用函數(shù)defuser_function_buttons():創(chuàng)建底部的功能按鈕區(qū)域bottom_containert.Frame(order_window)# 創(chuàng)建按鈕容器bottom_container.pack(pady20)# 放置容器# 刪除按鈕t.Button(bottom_container,text刪除選中菜品,commanddelete_dish,width15).pack(sideleft,padx10)# 預(yù)覽按鈕t.Button(bottom_container,text查看訂單預(yù)覽,commandview_preview,width15).pack(sideleft,padx10)# 下單按鈕t.Button(bottom_container,text確認(rèn)下單,commandxiadan_dish,width15).pack(sideleft,padx10)# 返回主界面按鈕t.Button(bottom_container,text返回主界面,commandlambda:[order_window.destroy(),main.main_window()],width15).pack(sideleft,padx10)# 加載菜單數(shù)據(jù)menu()# 初始化桌號init_desk_number()# 更新菜單函數(shù)defupdate_dish_list():更新菜品列表顯示# 清空當(dāng)前列表dish_listbox.delete(0,end)# 重新填充菜品列表fordish_objectinmenu_items.values():dish_listbox.insert(end,dish_object.display_in_menu())# 雙擊點餐函數(shù)defdouble_click_order(event):雙擊菜品列表觸發(fā)點餐功能# 獲取選中菜品的索引selected_indexdish_listbox.curselection()ifselected_index:indexselected_index[0]# 獲取菜品項文本dish_itemdish_listbox.get(index)# 解析菜品名dish_namedish_item.split( - )[0]# 從菜單中獲取菜品對象dish_objectmenu_items[dish_name]# 調(diào)用添加菜品函數(shù)傳遞菜品對象add_dish(dish_object)# 主窗口創(chuàng)建函數(shù)defcreate_order_window(desk_number未知桌號):創(chuàng)建并顯示訂單窗口 Args: desk_number: 桌號默認(rèn)為未知桌號 globalcurrent_desk_number,order_window,dish_listbox,selected_listbox current_desk_numberdesk_number# 搭建界面 # 1. 創(chuàng)建訂單窗口order_windowt.Tk()# 創(chuàng)建主窗口order_window.title(f大哥大飯店 - 桌號{current_desk_number})# 設(shè)置窗口標(biāo)題包含桌號order_window.geometry(800x500)# 窗口大小適當(dāng)增大以容納新按鈕# 2. 頂部歡迎信息welcome_labelt.Label(order_window,text歡迎來到大哥大飯店管理系統(tǒng),font(宋體,14))welcome_label.pack(pady10)# 3. 中間區(qū)域左側(cè)菜品表格 右側(cè)已選列表middle_containert.Frame(order_window)# 創(chuàng)建中間容器middle_container.pack(fillboth,expandTrue,padx20)# 左側(cè)菜品列表middle_containert.Frame(order_window)middle_container.pack(fillboth,expandTrue,padx20)# 左側(cè)菜品列表使用Listbox與右側(cè)已選列表保持一致格式dish_tablet.Frame(middle_container,bd1,reliefsolid)dish_table.pack(sideleft,fillboth,expandTrue,padx10)t.Label(dish_table,text菜品列表雙擊點餐,font(宋體,12)).pack(pady5)# 菜品列表框與右側(cè)已選列表保持一致格式dish_listboxt.Listbox(dish_table,width30,height10)dish_listbox.pack(pady5,padx5)# 初始填充菜品列表update_dish_list()dish_listbox.bind(Double-Button-1,double_click_order)# 中間功能按鈕區(qū)動態(tài)菜單功能 # 調(diào)用修改菜單數(shù)據(jù)函數(shù) modify_dish() # 右側(cè)已選菜品列表selected_containert.Frame(middle_container,bd1,reliefsolid)selected_container.pack(sideright,fillboth,expandTrue,padx10)t.Label(selected_container,text已選菜品,font(宋體,12)).pack(pady5)# 左側(cè)已選菜品列表框selected_listboxt.Listbox(selected_container,width30,height10)selected_listbox.pack(pady5,padx5)# 啟用用戶功能按鈕user_function_buttons()# 第四步運行程序 order_window.mainloop()# 啟動主循環(huán)顯示界面# 如果直接運行該文件則創(chuàng)建訂單窗口if__name____main__:# 初始化桌號init_desk_number()# 創(chuàng)建訂單窗口create_order_window(current_desk_number)3. guanli.py管理員管理Pythonimporttkinterastfromtkinterimportmessageboxasinfoimportjsonimportos,datetimeimportmain,shuju# 基本初始數(shù)據(jù)# 訂單信息ordered_items[]total_price0.0#類集合#辣度類classLadu:def__init__(self,name):self.namenamedef__str__(self):returnself.name#菜單類classDish:def__init__(self,name,price,category熱菜,laduLadu(微辣),beizhu無):self.namename self.priceprice self.categorycategory self.laduladu self.beizhubeizhu# 菜單顯示格式和__init__同級縮進defdisplay_in_menu(self):returnf{self.name}-{self.price}元 -{self.category}# 菜品字符串表示用于已選列表顯示def__str__(self):returnf{self.name}-{self.ladu}- 備注{self.beizhu}-{self.price}元# 菜品庫menu_items{}# 函數(shù)集合#保存菜單函數(shù)defsave_menu_to_json():#保存內(nèi)容到菜單文件globalmenu json_filer./菜單.jsontry:menu_data[]fora,(dish_name,dish_object)inenumerate(menu_items.items(),1):menu_data.append({id:a,name:dish_object.name,price:dish_object.price,category:dish_object.category})withopen(json_file,w,encodingutf-8)asfile:json.dump(menu_data,file,ensure_asciiFalse,indent4)print(f保存了{(lán)len(menu_data)}菜品)exceptExceptionase:print(f保存失敗原因為{str(e)})# 保存營業(yè)額函數(shù)defsave_sales_data():將當(dāng)前訂單保存為營業(yè)數(shù)據(jù)到JSON文件globalordered_items,total_price sales_file_pathr./營業(yè)數(shù)據(jù).jsontry:# 獲取當(dāng)前時間nowdatetime.datetime.now()current_datenow.strftime(%Y%m%d)# YYYYMMDD格式的日期current_timenow.strftime(%Y-%m-%d %H:%M:%S)# 完整時間格式# 讀取現(xiàn)有營業(yè)數(shù)據(jù)sales_data[]ifos.path.exists(sales_file_path):try:withopen(sales_file_path,r,encodingutf-8)asfile:file_contentfile.read().strip()iffile_content:sales_datajson.loads(file_content)exceptjson.JSONDecodeError:# 文件內(nèi)容不是有效的JSON創(chuàng)建一個新的空列表sales_data[]# 生成訂單編號當(dāng)天時間編號today_orders0fororderinsales_data:if訂單編號inorderandorder[訂單編號].startswith(current_date):today_orders1order_numberf{current_date}{today_orders1:03d}# 生成訂單編號# 準(zhǔn)備訂單詳情order_details[]fordishinordered_items:order_details.append({菜品名:dish.name,辣度:str(dish.ladu),備注:dish.beizhu,價格:dish.price})# 創(chuàng)建新訂單數(shù)據(jù)new_order{訂單編號:order_number,時間:current_time,桌號:未知桌號,# 管理系統(tǒng)訂單設(shè)置默認(rèn)桌號具體內(nèi)容:order_details,總金額:total_price}# 添加新訂單到營業(yè)數(shù)據(jù)sales_data.append(new_order)# 保存更新后的營業(yè)數(shù)據(jù)確保使用UTF-8編碼withopen(sales_file_path,w,encodingutf-8,newline)asfile:json.dump(sales_data,file,ensure_asciiFalse,indent4,defaultstr)print(f營業(yè)數(shù)據(jù)保存成功{order_number})exceptExceptionase:print(f保存營業(yè)數(shù)據(jù)失敗{str(e)})info.showerror(錯誤,f保存營業(yè)數(shù)據(jù)失敗{str(e)})#清空當(dāng)前訂單函數(shù)defclear_current_order():清空當(dāng)前訂單的所有菜品和總價globalordered_items,total_price ordered_items[]# 清空已點菜品列表total_price0.0# 清空總價selected_listbox.delete(0,end)# 清空列表框顯示# 讀取菜單函數(shù)defmenu():#從json文件加載菜單數(shù)據(jù)并傳喚為菜單globalmenu_items json_pathr./菜單.jsontry:withopen(json_path,r,encodingutf-8)asfile:menu_datajson.load(file)# 將json數(shù)據(jù)轉(zhuǎn)換為dish對象字典menu_items{}foriteminmenu_data:dish_nameitem[name]dish_priceitem[price]dish_categoryitem.get(category,熱菜)menu_items[dish_name]Dish(dish_name,dish_price,dish_category)print(f共打印了{(lán)len(menu_items)}個菜品)exceptFileNotFoundError:print(fJSON文件{json}為找到)# 備用方案menu_items{麻辣香鍋:Dish(麻辣香鍋,58,熱菜),水煮魚:Dish(水煮魚,88,熱菜),回鍋肉:Dish(回鍋肉,42,熱菜),番茄炒蛋:Dish(番茄炒蛋,22,熱菜),魚香肉絲:Dish(魚香肉絲,38,熱菜),}save_menu_to_json()# 加菜函數(shù)defadd_dish(dish_object):加菜函數(shù)說明 點擊下單后彈出備注窗口 功能如下 辣度選擇 備注 取消下單 彈出辣度選擇窗口讓用戶選擇菜品的辣度和備注# 創(chuàng)建新的辣度選擇窗口beizhu_windowt.Toplevel()beizhu_window.title(f選擇{dish_object.name}的辣度)beizhu_window.geometry(300x250)# 固定窗口大小# 辣度選擇單選按鈕ladu_vart.StringVar(value微辣)# 默認(rèn)微辣t.Label(beizhu_window,text選擇辣度).pack(pady5)t.Radiobutton(beizhu_window,text清淡,variableladu_var,value清淡).pack()t.Radiobutton(beizhu_window,text微辣,variableladu_var,value微辣).pack()t.Radiobutton(beizhu_window,text中辣,variableladu_var,value中辣).pack()t.Radiobutton(beizhu_window,text爆辣,variableladu_var,value爆辣).pack()# 備注輸入框t.Label(beizhu_window,text備注忌口等).pack(pady5)beizhu_vart.StringVar(value無)# 默認(rèn)無備注beizhu_entryt.Entry(beizhu_window,textvariablebeizhu_var)beizhu_entry.pack()# 確認(rèn)添加按鈕函數(shù)defxiadan():確認(rèn)添加菜品到訂單selected_ladu_nameladu_var.get()# 獲取選擇的辣度名稱selected_beizhubeizhu_var.get()# 獲取備注# 創(chuàng)建辣度對象selected_laduLadu(selected_ladu_name)# 創(chuàng)建新的菜品對象包含用戶選擇的辣度和備注selected_dishDish(dish_object.name,dish_object.price,dish_object.category,selected_ladu,selected_beizhu)# 將菜品對象添加到訂單ordered_items.append(selected_dish)globaltotal_price# 聲明使用全局變量total_pricedish_object.price# 更新總價# 更新右側(cè)已選菜品列表selected_listbox.insert(end,str(selected_dish))# 關(guān)閉辣度選擇窗口beizhu_window.destroy()# 顯示成功信息info.showinfo(提示,f{dish_object.name}已加入訂單)# 返回主界面函數(shù)defback():返回主界面不添加菜品beizhu_window.destroy()# 創(chuàng)建按鈕容器button_framet.Frame(beizhu_window)button_frame.pack(pady10)# 添加按鈕t.Button(button_frame,text確認(rèn)添加,commandxiadan).pack(sideleft,padx5)t.Button(button_frame,text返回,commandback).pack(sideleft,padx5)#刪菜函數(shù)defdelete_dish():刪除選中的已點菜品# 獲取選中菜品的索引selected_indexselected_listbox.curselection()ifnotselected_index:# 如果沒有選中任何菜品則顯示提示info.showwarning(提示,先選中要刪除的菜品)returnindexselected_index[0]# 從訂單中刪除菜品對象并更新總價deleted_dishordered_items.pop(index)globaltotal_price total_price-deleted_dish.price# 更新總價# 從列表框顯示中刪除selected_listbox.delete(index)info.showinfo(提示,f已刪除{deleted_dish.name})# 預(yù)覽菜單函數(shù)defview_preview():顯示當(dāng)前訂單的預(yù)覽信息ifnotordered_items:# 如果沒有點任何菜品則顯示提示info.showwarning(提示,還沒點任何菜品)return# 組裝預(yù)覽內(nèi)容preview_content 訂單預(yù)覽
fornumber,dish_objectinenumerate(ordered_items,1):preview_contentf{number}.{dish_object.name}-{dish_object.ladu}- 備注{dish_object.beizhu}-{dish_object.price}元
preview_contentf
總價{total_price}元# 顯示彈窗info.showinfo(訂單預(yù)覽,preview_content)# 下單函數(shù)defxiadan_dish():確認(rèn)當(dāng)前訂單并保存營業(yè)數(shù)據(jù)ifnotordered_items:info.showwarning(提示,沒點菜品不能下單)return# 組裝訂單信息order_content 下單成功
fornumber,dish_objectinenumerate(ordered_items,1):order_contentf{number}.{dish_object.name}-{dish_object.ladu}- 備注{dish_object.beizhu}-{dish_object.price}元
order_contentf
總價{total_price}元
坐等上菜info.showinfo(下單成功,order_content)# 保存營業(yè)數(shù)據(jù)到JSON文件save_sales_data()# 清空當(dāng)前訂單clear_current_order()# 用戶/加菜功能函數(shù)集合調(diào)用函數(shù)defuser_function_buttons():創(chuàng)建底部的功能按鈕區(qū)域bottom_containert.Frame(order_window)# 創(chuàng)建按鈕容器bottom_container.pack(pady20)# 放置容器# 刪除按鈕t.Button(bottom_container,text刪除選中菜品,commanddelete_dish,width15).pack(sideleft,padx10)# 預(yù)覽按鈕t.Button(bottom_container,text查看訂單預(yù)覽,commandview_preview,width15).pack(sideleft,padx10)# 下單按鈕t.Button(bottom_container,text確認(rèn)下單,commandxiadan_dish,width15).pack(sideleft,padx10)# 數(shù)據(jù)分析按鈕t.Button(bottom_container,text數(shù)據(jù)分析,commandlambda:shuju.shuju_gui(order_window),width15).pack(sideleft,padx10)# 返回主界面按鈕t.Button(bottom_container,text返回主界面,commandlambda:[order_window.destroy(),main.main_window()],width15).pack(sideleft,padx10)# 加載菜單數(shù)據(jù)menu()# 修改菜單數(shù)據(jù)函數(shù)管理功能defmodify_dish():菜單管理功能包括添加、修改、刪除菜品# 添加新菜品defadd_new_dish():添加新菜品到菜單new_dish_windowt.Toplevel()new_dish_window.title(添加新菜品)new_dish_window.geometry(300x250)# 增加窗口高度以容納品類選擇t.Label(new_dish_window,text菜品名).pack(pady5)new_dish_namet.StringVar()t.Entry(new_dish_window,textvariablenew_dish_name).pack()t.Label(new_dish_window,text價格).pack(pady5)new_pricet.StringVar()t.Entry(new_dish_window,textvariablenew_price).pack()# 添加品類選擇t.Label(new_dish_window,text品類).pack(pady5)new_categoryt.StringVar(value熱菜)# 默認(rèn)熱菜category_options[熱菜,涼菜,主食,飲料]category_dropdownt.OptionMenu(new_dish_window,new_category,*category_options)category_dropdown.pack()defconfirm_add_new_dish():確認(rèn)添加新菜品dish_namenew_dish_name.get()# 獲取菜品名pricenew_price.get()# 獲取價格categorynew_category.get()# 獲取品類ifnotdish_nameornotprice:info.showwarning(提示,請輸入菜品名和價格)returntry:pricefloat(price)# 轉(zhuǎn)換價格為浮點數(shù)menu_items[dish_name]Dish(dish_name,price,category)# 創(chuàng)建新菜品update_dish_list()# 更新菜品列表顯示save_menu_to_json()# 保存到JSON文件new_dish_window.destroy()info.showinfo(提示,新菜品添加成功)exceptValueError:info.showwarning(提示,價格必須是數(shù)字)defback():返回菜單管理界面new_dish_window.destroy()button_framet.Frame(new_dish_window)button_frame.pack(pady10)t.Button(button_frame,text確認(rèn)添加,commandconfirm_add_new_dish,width12).pack(sideleft,padx5)t.Button(button_frame,text返回,commandback,width12).pack(sideleft,padx5)# 修改菜品價格defmodify_dish_price():修改現(xiàn)有菜品的價格modify_windowt.Toplevel()modify_window.title(修改菜品價格)modify_window.geometry(300x200)t.Label(modify_window,text選擇菜品).pack(pady5)selected_menu_itemt.StringVar()dish_dropdownt.OptionMenu(modify_window,selected_menu_item,*menu_items.keys())dish_dropdown.pack()t.Label(modify_window,text新價格).pack(pady5)new_pricet.StringVar()t.Entry(modify_window,textvariablenew_price).pack()defconfirm_modify_price():確認(rèn)修改菜品價格dish_nameselected_menu_item.get()# 獲取選擇的菜品pricenew_price.get()# 獲取新價格ifnotdish_nameornotprice:info.showwarning(提示,請選擇菜品并輸入新價格)returntry:pricefloat(price)# 轉(zhuǎn)換價格為浮點數(shù)# 更新菜品對象價格dish_objectmenu_items[dish_name]dish_object.priceprice update_dish_list()# 更新菜品列表顯示save_menu_to_json()# 保存到JSON文件modify_window.destroy()info.showinfo(提示,價格修改成功)exceptValueError:info.showwarning(提示,價格必須是數(shù)字)defback():返回菜單管理界面modify_window.destroy()button_framet.Frame(modify_window)button_frame.pack(pady10)t.Button(button_frame,text確認(rèn)修改,commandconfirm_modify_price,width12).pack(sideleft,padx5)t.Button(button_frame,text返回,commandback,width12).pack(sideleft,padx5)# 從菜單中刪除菜品defdelete_dish_from_menu():從菜單中刪除菜品delete_windowt.Toplevel()delete_window.title(刪除菜品)delete_window.geometry(300x150)t.Label(delete_window,text選擇要刪除的菜品).pack(pady5)selected_menu_itemt.StringVar()dish_dropdownt.OptionMenu(delete_window,selected_menu_item,*menu_items.keys())dish_dropdown.pack()defconfirm_delete():確認(rèn)刪除菜品dish_nameselected_menu_item.get()# 獲取要刪除的菜品ifnotdish_name:info.showwarning(提示,請選擇要刪除的菜品)returnifinfo.askyesno(確認(rèn),f確定要刪除{dish_name}嗎):delmenu_items[dish_name]# 刪除菜品update_dish_list()# 更新菜品列表顯示save_menu_to_json()# 保存到JSON文件delete_window.destroy()info.showinfo(提示,菜品刪除成功)defback():返回菜單管理界面delete_window.destroy()button_framet.Frame(delete_window)button_frame.pack(pady10)t.Button(button_frame,text確認(rèn)刪除,commandconfirm_delete,width12).pack(sideleft,padx5)t.Button(button_frame,text返回,commandback,width12).pack(sideleft,padx5)# 創(chuàng)建功能按鈕容器function_button_areat.Frame(dish_table)function_button_area.pack(pady10)# 添加按鈕t.Button(function_button_area,text添加新菜品,commandadd_new_dish).pack(sideleft,padx5)t.Button(function_button_area,text修改菜品價格,commandmodify_dish_price).pack(sideleft,padx5)t.Button(function_button_area,text刪除菜品,commanddelete_dish_from_menu).pack(sideleft,padx5)# 更新菜單函數(shù)defupdate_dish_list():更新菜品列表顯示# 清空當(dāng)前列表dish_listbox.delete(0,end)# 重新填充菜品列表fordish_objectinmenu_items.values():dish_listbox.insert(end,dish_object.display_in_menu())#雙擊點餐函數(shù)defdouble_click_order(event):雙擊菜品列表觸發(fā)點餐功能# 獲取選中菜品的索引selected_indexdish_listbox.curselection()ifselected_index:indexselected_index[0]# 獲取菜品項文本dish_itemdish_listbox.get(index)# 解析菜品名dish_namedish_item.split( - )[0]# 從菜單中獲取菜品對象dish_objectmenu_items[dish_name]# 調(diào)用添加菜品函數(shù)傳遞菜品對象add_dish(dish_object)# 主窗口創(chuàng)建函數(shù)defcreate_guanli_window():創(chuàng)建并顯示管理系統(tǒng)窗口globalorder_window,dish_listbox,selected_listbox,dish_table# 搭建界面 # 1. 創(chuàng)建訂單窗口order_windowt.Tk()# 創(chuàng)建主窗口order_window.title(大哥大飯店)# 設(shè)置窗口標(biāo)題order_window.geometry(800x500)# 窗口大小適當(dāng)增大以容納新按鈕# 2. 頂部歡迎信息welcome_labelt.Label(order_window,text歡迎來到大哥大飯店管理系統(tǒng),font(宋體,14))welcome_label.pack(pady10)# 3. 中間區(qū)域左側(cè)菜品表格 右側(cè)已選列表middle_containert.Frame(order_window)# 創(chuàng)建中間容器middle_container.pack(fillboth,expandTrue,padx20)# 左側(cè)菜品列表middle_containert.Frame(order_window)middle_container.pack(fillboth,expandTrue,padx20)# 左側(cè)菜品列表使用Listbox與右側(cè)已選列表保持一致格式dish_tablet.Frame(middle_container,bd1,reliefsolid)dish_table.pack(sideleft,fillboth,expandTrue,padx10)t.Label(dish_table,text菜品列表雙擊點餐,font(宋體,12)).pack(pady5)# 菜品列表框與右側(cè)已選列表保持一致格式dish_listboxt.Listbox(dish_table,width30,height10)dish_listbox.pack(pady5,padx5)# 更新菜品列表的函數(shù)可調(diào)用以刷新顯示# 初始填充菜品列表update_dish_list()dish_listbox.bind(Double-Button-1,double_click_order)# 中間功能按鈕區(qū)動態(tài)菜單功能 # 調(diào)用修改菜單數(shù)據(jù)函數(shù)modify_dish()# 右側(cè)已選菜品列表selected_containert.Frame(middle_container,bd1,reliefsolid)selected_container.pack(sideright,fillboth,expandTrue,padx10)t.Label(selected_container,text已選菜品,font(宋體,12)).pack(pady5)# 左側(cè)已選菜品列表框selected_listboxt.Listbox(selected_container,width30,height10)selected_listbox.pack(pady5,padx5)# 啟用用戶功能按鈕user_function_buttons()# 第四步運行程序 order_window.mainloop()# 啟動主循環(huán)顯示界面# 如果直接運行該文件則創(chuàng)建管理系統(tǒng)窗口if__name____main__:create_guanli_window()4. shuju.py數(shù)據(jù)統(tǒng)計與可視化Pythonimportjsonimportosimportdatetimeimporttkinterastfromtkinterimportmessageboxasinfo,ttkimportmatplotlib.pyplotaspltfrommatplotlib.backends.backend_tkaggimportFigureCanvasTkAgg# 設(shè)置matplotlib支持中文plt.rcParams[font.sans-serif][SimHei]# 使用黑體字體支持中文顯示plt.rcParams[axes.unicode_minus]False# 負(fù)號顯示#讀取文件數(shù)據(jù)defdu_qu_shuju():讀取文件數(shù)據(jù) 返回值 list:包含所有訂單數(shù)據(jù)的列表如果失敗返回空列表 #讀取當(dāng)前目錄以絕對路徑獲取文件數(shù)據(jù)dangqian_diros.path.dirname(os.path.abspath(__file__))shujuos.path.join(dangqian_dir,營業(yè)數(shù)據(jù).json)yingye_data[]try:ifos.path.exists(shuju):withopen(shuju,r,encodingutf-8)asfile:contentfile.read().strip()ifcontent:yingye_datajson.loads(content)returnyingye_dataexceptExceptionase:info.showerror(錯誤,f讀取數(shù)據(jù)失敗)return[]#小時函數(shù)defhour_sales(data,riqi):按小時統(tǒng)計指定日期的銷售額 參數(shù): data: 包含所有訂單數(shù)據(jù)的列表 riqi: 要統(tǒng)計的日期格式為YYYY-MM-DD 命名 hour_sales: 符合條件的日期 order_time: 訂單時間 返回值: dict: 包含每個小時銷售額的字典鍵為小時如00-23值為銷售額 hour_sales{}# 遍歷所有訂單fororderindata:try:# 查找關(guān)鍵字存儲起來time_keyNoneforkeyinorder:if時間inkey:time_keykeybreak# 修正沒有找到時間字段才跳過iftime_keyisNone:continue# 解析訂單時間order_timedatetime.datetime.strptime(order[time_key],%Y-%m-%d %H:%M:%S)# 獲取訂單日期order_dateorder_time.strftime(%Y-%m-%d)# 只統(tǒng)計選擇的日期iforder_date!riqi:continue# 提取訂單時間的時段hourorder_time.strftime(%H)# 修正查找總金額字段邏輯total_keyNoneforkeyinorder:if總金額inkey:total_keykeybreak# 沒有總金額字段則跳過iftotal_keyisNone:continue# 獲取訂單金額并轉(zhuǎn)換為數(shù)字hour_qianfloat(order[total_key])# 確保金額是數(shù)字類型# 小時銷售額累加邏輯ifhourinhour_sales:hour_sales[hour]hour_qianelse:hour_sales[hour]hour_qian# 出錯則跳到下一個訂單exceptExceptionase:continue# 確保所有小時00-23都有數(shù)據(jù)沒有銷售額的小時設(shè)置為0forhourinrange(24):hour_strf{hour:02d}ifhour_strnotinhour_sales:hour_sales[hour_str]0.0# 按小時排序并返回結(jié)果returndict(sorted(hour_sales.items()))#天數(shù)函數(shù)defday_sales(data):日統(tǒng)計表 參數(shù) data訂單數(shù)據(jù)內(nèi)容 返回值 weekly_sales: 包含每天銷售額的字典以周為一個范圍 weekdays[周一,周二,周三,周四,周五,周六,周日]#初始化每周各天銷售額為0weekly_sales{day:0fordayinweekdays}# 遍歷訂單獲取數(shù)據(jù)fororderindata:try:time_keyNoneforkeyinorder:if時間inkey:time_keykeybreakiftime_keyisNone:continue# 解析訂單時間并通過datetime庫分析為周幾order_timedatetime.datetime.strptime(order[time_key],%Y-%m-%d %H:%M:%S)# 獲取星期幾的索引0一6日weekday_indexorder_time.weekday()# 根據(jù)索引獲取星期幾的中文名稱weekday_nameweekdays[weekday_index]total_keyNoneforkeyinorder:if總金額inkey:total_keykeybreakiftotal_keyisNone:continue# 獲取訂單金額為浮點數(shù)total_amountfloat(order[total_key])# 累加每周各天總金額weekly_sales[weekday_name]total_amountexceptExceptionase:print(該訂單出錯跳過處理下一單)continuereturnweekly_sales#畫圖函數(shù)defcreate_tubiao(data,title,x_label,y_label,horizontalFalse):創(chuàng)建條形圖 參數(shù): data: 要顯示的數(shù)據(jù)字典 title: 圖表標(biāo)題 x_label: X軸標(biāo)簽 y_label: Y軸標(biāo)簽 horizontal: 是否創(chuàng)建水平條形圖默認(rèn)為False垂直條形圖 返回值: matplotlib.figure.Figure: 創(chuàng)建的圖表對象 # 從數(shù)據(jù)字典中提取標(biāo)簽和數(shù)值labelslist(data.keys())amountslist(data.values())# 根據(jù)是否為水平條形圖和數(shù)據(jù)量調(diào)整圖表大小使其更緊湊ifhorizontalandlen(labels)10:# 水平條形圖且數(shù)據(jù)量較多時增加高度以便完整顯示fig,axplt.subplots(figsize(10,8))else:# 默認(rèn)圖表大小fig,axplt.subplots(figsize(8,5))# 創(chuàng)建條形圖ifhorizontal:# 創(chuàng)建水平條形圖barsax.barh(labels,amounts,colorlightblue)else:# 創(chuàng)建垂直條形圖barsax.bar(labels,amounts,colorlightgreen)# 設(shè)置圖表標(biāo)題和坐標(biāo)軸標(biāo)簽ax.set_title(title,fontsize14)ax.set_xlabel(x_label,fontsize12)ax.set_ylabel(y_label,fontsize12)# 在條形圖上顯示數(shù)值forbarinbars:ifhorizontal:# 水平條形圖數(shù)值顯示在條形右側(cè)widthbar.get_width()ax.text(width1,bar.get_y()bar.get_height()/2,f{width:.2f},vacenter,fontsize10)else:# 垂直條形圖數(shù)值顯示在條形頂部heightbar.get_height()ax.text(bar.get_x()bar.get_width()/2,height1,f{height:.2f},hacenter,fontsize10)# 添加網(wǎng)格線ax.grid(axisxifhorizontalelsey,linestyle--,alpha0.7)plt.tight_layout()# 自動調(diào)整圖表布局returnfig#數(shù)據(jù)窗口defshuju_gui(parentNone): 參數(shù)parent:父窗口如果為None則創(chuàng)建一個新的根窗口 ifparentisNone:roott.Tk()else:roott.Toplevel(parent)root.title(營業(yè)數(shù)據(jù)分析)root.geometry(1200x800)root.resizable(widthTrue,heightTrue)sales_datadu_qu_shuju()# 獲取所有可用日期all_datesset()fororderinsales_data:try:# 找到時間字段time_keyNoneforkeyinorder:if時間inkeyor時inkey:time_keykeybreak# 如果有時間字段提取日期iftime_key:order_timedatetime.datetime.strptime(order[time_key],%Y-%m-%d %H:%M:%S)all_dates.add(order_time.strftime(%Y-%m-%d))except:# 如果處理出錯跳過此訂單continue# 倒序排序方便查看近期數(shù)據(jù)daoxun_datessorted(list(all_dates),reverseTrue)# 選擇最新的日期作為默認(rèn)值mongren_datedaoxun_dates[0]ifdaoxun_dateselsecontrol_framettk.LabelFrame(root,text數(shù)據(jù)選擇,padding10)control_frame.pack(fillt.X,padx10,pady10)ttk.Label(control_frame,text查看方式).pack(sidet.LEFT,padx10,pady10)view_typet.StringVar(value按天)defupdate_tubiao():更新圖表ifview_type.get()按天:# 按天查看 - 顯示每小時銷售額datedate_combo.get()ifnotdate:info.showinfo(提示,請選擇日期)return# 統(tǒng)計該日期的每小時銷售額hourly_saleshour_sales(sales_data,date)titlef{date}每小時銷售額# 創(chuàng)建水平條形圖figcreate_tubiao(hourly_sales,title,銷售額元,小時,horizontalTrue)# 計算并更新統(tǒng)計信息totalsum(hourly_sales.values())# 總銷售額max_hourmax(hourly_sales,keyhourly_sales.get)# 銷售額最高的小時max_saleshourly_sales[max_hour]# 最高銷售額else:# 按星期查看 - 顯示每周各天銷售額# 統(tǒng)計每周各天的銷售額weekly_salesday_sales(sales_data)title每周各天銷售額統(tǒng)計# 創(chuàng)建垂直條形圖figcreate_tubiao(weekly_sales,title,星期,銷售額元,horizontalFalse)# 計算并更新統(tǒng)計信息totalsum(weekly_sales.values())# 總銷售額max_daymax(weekly_sales,keyweekly_sales.get)# 銷售額最高的星期max_salesweekly_sales[max_day]# 最高銷售額# 更新圖表# 首先清除舊的圖表顯示forwidgetinchart_frame.winfo_children():widget.destroy()# 創(chuàng)建新的canvas并顯示canvasFigureCanvasTkAgg(fig,masterchart_frame)canvas.draw()canvas.get_tk_widget().pack(fillt.BOTH,expandTrue,padx10,pady10)# 更新統(tǒng)計信息stats_label.config(textf總銷售額{total:.2f}元 | 最高{max_sales:.2f}元)# 按天查看按鈕look_day_btnttk.Radiobutton(control_frame,text按天,variableview_type,value按天,commandupdate_tubiao)look_day_btn.pack(sidet.LEFT,padx5)# 按星期查看按鈕look_week_btnttk.Radiobutton(control_frame,text按星期,variableview_type,value按星期,commandupdate_tubiao)look_week_btn.pack(sidet.LEFT,padx5)# 日期選擇下拉框ttk.Label(control_frame,text日期).pack(sidet.LEFT,padx5)date_combottk.Combobox(control_frame,valuesdaoxun_dates,statereadonly,width12)date_combo.pack(sidet.LEFT,padx5)# 設(shè)置默認(rèn)選中最新的日期ifdaoxun_dates:date_combo.set(daoxun_dates[0])# 刷新按鈕refresh_btnttk.Button(control_frame,text刷新,commandupdate_tubiao)refresh_btn.pack(sidet.RIGHT,padx10)# 圖表顯示區(qū)域chart_framettk.Frame(root)chart_frame.pack(fillt.BOTH,expandTrue,padx10,pady10)# 創(chuàng)建初始圖表ifdaoxun_dates:# 有數(shù)據(jù)時顯示最新日期的每小時銷售額hourly_saleshour_sales(sales_data,daoxun_dates[0])titlef{daoxun_dates[0]}每小時銷售額figcreate_tubiao(hourly_sales,title,銷售額元,小時,horizontalTrue)totalsum(hourly_sales.values())max_hourmax(hourly_sales,keyhourly_sales.get)max_saleshourly_sales[max_hour]else:# 無數(shù)據(jù)時顯示提示信息fig,axplt.subplots(figsize(10,6))ax.set_title(暫無數(shù)據(jù),fontsize16)total0max_sales0# 嵌入圖表到界面canvasFigureCanvasTkAgg(fig,masterchart_frame)canvas.draw()canvas.get_tk_widget().pack(fillt.BOTH,expandTrue,padx10,pady10)# 統(tǒng)計信息顯示stats_labelttk.Label(root,textf總銷售額{total:.2f}元 | 最高{max_sales:.2f}元,font(Arial,12))stats_label.pack(fillt.X,padx10,pady10)# 增加底部邊距使界面更美觀# 啟動主循環(huán)root.mainloop()if__name____main__:shuju_gui()5. 數(shù)據(jù)文件示例菜單.jsonJSON[{id:1,name:宮保雞丁,price:28,category:熱菜},{id:2,name:魚香肉絲,price:25,category:熱菜},// ... 共19道菜]用戶信息.json默認(rèn)管理員賬號JSON[{賬號:1,密碼:123,角色:管理者},{賬號:123,密碼:456,角色:管理者}]營業(yè)數(shù)據(jù).json訂單記錄示例JSON[{訂單編號:20251212001,時間:2025-12-12 10:30:00,桌號:1,具體內(nèi)容:[...],總金額:53.0}// ... 更多訂單]運行方式直接雙擊 main.py 即可啟動。首次運行會自動創(chuàng)建默認(rèn)數(shù)據(jù)文件??偨Y(jié)這個項目雖然不大但幾乎涵蓋了 Tkinter 開發(fā)的所有核心知識點窗口與控件布局事件綁定雙擊、按鈕模塊間傳參與跳轉(zhuǎn)JSON 文件讀寫持久化Matplotlib 嵌入 GUI 實現(xiàn)動態(tài)圖表面向?qū)ο蠓庋bDish、Ladu 類通過這個項目我對 Python 桌面應(yīng)用開發(fā)有了更深的理解也體會到模塊化設(shè)計和異常處理的重要性。項目還有很多可擴展空間比如完善管理員菜品增刪改界面加入打印小票功能引入 SQLite 數(shù)據(jù)庫開發(fā)網(wǎng)絡(luò)版支持多臺平板同時點餐引用Tkinter的ttk進行美化喜歡的話歡迎 Star 或 Fork后續(xù)有更新會繼續(xù)分享完整源碼下載直接復(fù)制以上所有文件到同一文件夾即可運行。 如果有任何問題歡迎在評論區(qū)交流