Python 基于 Tkinter 实现桌面电商购物系统

发布时间:2026/9/5 7:15:19
Python 基于 Tkinter 实现桌面电商购物系统 一、项目简介1.1 项目说明本项目使用 Python Tkinter 开发一款桌面版电商购物系统不需要连接数据库全部数据内存模拟实现。实现用户登录、商品浏览、加入购物车、购物车管理、结算下单、退出登录完整电商流程。适合 Python 课程设计、大作业、毕业设计练手。技术栈Python 3.xTkinterGUI 图形界面ttk 组件美化界面decimal 高精度金额计算避免浮点数精度 bug内存模拟用户库、商品库无需 MySQL 数据库1.2 实现功能清单用户登录验证内置两套测试账号登录窗口居中密码隐藏输入商品列表表格展示ID、商品名称、价格、分类、商品描述选择商品自定义购买数量加入购物车独立购物车子窗口展示商品、单价、数量、小计金额清空购物车功能结算下单订单确认下单成功清空购物车退出登录返回登录界面窗口居中弹窗提示消息框交互使用 decimal 处理金额解决浮点运算误差1.3 测试账号用户名密码昵称admin123456系统管理员user1111111普通用户二、项目整体架构项目采用面向对象编程拆分多个类CartService购物车业务逻辑服务类纯粹业务不操作 UI实现添加、删除、清空、计算总价LoginWindow登录主窗口 (Tk)MainWindow系统主界面商品展示页面 (Tk)CartWindow购物车弹窗 (Toplevel)子窗口模拟内存数据库USER_DB 用户字典PRODUCTS商品列表三、完整源代码import tkinter as tk from tkinter import ttk, messagebox, simpledialog import decimal # 数据模型 # 模拟用户数据库 USER_DB { admin: {password: 123456, nickname: 系统管理员}, user1: {password: 111111, nickname: 普通用户} } # 模拟商品数据库 PRODUCTS [ {id: 1, name: 华为Mate70 Pro, price: decimal.Decimal(6999.00), category: 手机, desc: 鸿蒙系统麒麟芯片}, {id: 2, name: 苹果iPhone 16, price: decimal.Decimal(7999.00), category: 手机, desc: A18芯片iOS 18}, {id: 3, name: 小米笔记本Pro 2025, price: decimal.Decimal(5999.00), category: 电脑, desc: 酷睿i716G内存}, {id: 4, name: 华为平板MatePad Pro, price: decimal.Decimal(2999.00), category: 平板, desc: 12.6英寸鸿蒙4.0}, {id: 5, name: AirPods Pro 2, price: decimal.Decimal(1499.00), category: 耳机, desc: 主动降噪无线充电} ] # 购物车服务类 class CartService: def __init__(self): self.cart_items [] # 购物车项[(product, quantity), ...] def add_to_cart(self, product, quantity): 添加商品到购物车已存在则更新数量 if quantity 0: raise ValueError(购买数量必须大于0) # 检查商品是否已在购物车 for idx, (p, q) in enumerate(self.cart_items): if p[id] product[id]: self.cart_items[idx] (p, q quantity) return # 新增商品到购物车 self.cart_items.append((product, quantity)) def remove_from_cart(self, product_id): 从购物车移除指定商品 self.cart_items [(p, q) for p, q in self.cart_items if p[id] ! product_id] def clear_cart(self): 清空购物车 self.cart_items.clear() def get_cart_items(self): 获取购物车所有商品 return self.cart_items.copy() def calculate_total(self): 计算购物车总金额 total decimal.Decimal(0.00) for product, quantity in self.cart_items: total product[price] * quantity return total def is_empty(self): 检查购物车是否为空 return len(self.cart_items) 0 # 登录窗口 class LoginWindow(tk.Tk): def __init__(self): super().__init__() self.title(电商系统 - 用户登录) self.geometry(450x350) self.resizable(False, False) self.center_window() # 窗口居中 # 初始化购物车服务 self.cart_service CartService() # 创建UI self.create_ui() def center_window(self): 窗口居中显示 self.update_idletasks() width self.winfo_width() height self.winfo_height() x (self.winfo_screenwidth() // 2) - (width // 2) y (self.winfo_screenheight() // 2) - (height // 2) self.geometry(f{width}x{height}{x}{y}) def create_ui(self): 创建登录界面 # 主面板 main_frame ttk.Frame(self, padding30) main_frame.pack(expandTrue, filltk.BOTH) # 标题 title_label ttk.Label(main_frame, textPython电商购物系统, font(微软雅黑, 20, bold)) title_label.pack(pady(0, 30)) # 用户名行 user_frame ttk.Frame(main_frame) user_frame.pack(filltk.X, pady10) ttk.Label(user_frame, text用户名, font(微软雅黑, 12)).pack(sidetk.LEFT) self.username_var tk.StringVar() username_entry ttk.Entry(user_frame, textvariableself.username_var, font(微软雅黑, 12), width25) username_entry.pack(sidetk.LEFT, padx10) # 密码行 pwd_frame ttk.Frame(main_frame) pwd_frame.pack(filltk.X, pady10) ttk.Label(pwd_frame, text密 码, font(微软雅黑, 12)).pack(sidetk.LEFT) self.pwd_var tk.StringVar() pwd_entry ttk.Entry(pwd_frame, textvariableself.pwd_var, font(微软雅黑, 12), width25, show*) pwd_entry.pack(sidetk.LEFT, padx10) # 登录按钮 login_btn ttk.Button(main_frame, text登录, commandself.login) login_btn.pack(pady20) # 提示信息 tip_label ttk.Label(main_frame, text测试账号admin/123456 | user1/111111, font(微软雅黑, 10)) tip_label.pack() def login(self): 处理登录逻辑 username self.username_var.get().strip() password self.pwd_var.get().strip() # 验证输入 if not username: messagebox.showerror(错误, 请输入用户名) return if not password: messagebox.showerror(错误, 请输入密码) return # 验证用户 user USER_DB.get(username) if not user or user[password] ! password: messagebox.showerror(错误, 用户名或密码错误) self.pwd_var.set() # 清空密码框 return # 登录成功打开主窗口 messagebox.showinfo(成功, f登录成功欢迎您{user[nickname]}) self.destroy() # 关闭登录窗口 MainWindow(user, self.cart_service).mainloop() # 主窗口商品展示 class MainWindow(tk.Tk): def __init__(self, user, cart_service): super().__init__() self.title(f电商系统 - {user[nickname]}) self.geometry(900x600) self.resizable(True, True) self.center_window() # 初始化数据 self.current_user user self.cart_service cart_service self.cart_window None # 购物车窗体引用 # 创建UI self.create_ui() def center_window(self): 窗口居中 self.update_idletasks() width self.winfo_width() height self.winfo_height() x (self.winfo_screenwidth() // 2) - (width // 2) y (self.winfo_screenheight() // 2) - (height // 2) self.geometry(f{width}x{height}{x}{y}) def create_ui(self): 创建主界面 # 顶部工具栏 toolbar ttk.Frame(self) toolbar.pack(filltk.X, padx10, pady10) # 购物车按钮 cart_btn ttk.Button(toolbar, text我的购物车, commandself.open_cart) cart_btn.pack(sidetk.RIGHT) # 退出按钮 exit_btn ttk.Button(toolbar, text退出登录, commandself.logout) exit_btn.pack(sidetk.RIGHT, padx10) # 商品表格 product_frame ttk.Frame(self) product_frame.pack(expandTrue, filltk.BOTH, padx10, pady10) # 表格列名 columns (ID, 商品名称, 价格(元), 分类, 描述) self.product_tree ttk.Treeview(product_frame, columnscolumns, showheadings, height15) # 设置列标题和宽度 for col in columns: self.product_tree.heading(col, textcol) if col 商品名称: self.product_tree.column(col, width200) elif col 描述: self.product_tree.column(col, width250) else: self.product_tree.column(col, width100) # 滚动条 scrollbar ttk.Scrollbar(product_frame, orienttk.VERTICAL, commandself.product_tree.yview) self.product_tree.configure(yscrollcommandscrollbar.set) # 布局表格和滚动条 self.product_tree.pack(sidetk.LEFT, expandTrue, filltk.BOTH) scrollbar.pack(sidetk.RIGHT, filltk.Y) # 加载商品数据 self.load_products() # 底部操作区 op_frame ttk.Frame(self) op_frame.pack(filltk.X, padx10, pady10) # 数量输入 ttk.Label(op_frame, text购买数量).pack(sidetk.LEFT) self.quantity_var tk.StringVar(value1) quantity_entry ttk.Entry(op_frame, textvariableself.quantity_var, width10) quantity_entry.pack(sidetk.LEFT, padx10) # 加入购物车按钮 add_cart_btn ttk.Button(op_frame, text加入购物车, commandself.add_to_cart) add_cart_btn.pack(sidetk.LEFT) def load_products(self): 加载商品数据到表格 # 清空现有数据 for item in self.product_tree.get_children(): self.product_tree.delete(item) # 添加商品 for product in PRODUCTS: self.product_tree.insert(, tk.END, values( product[id], product[name], f{product[price]:.2f}, product[category], product[desc] )) def add_to_cart(self): 添加选中商品到购物车 # 获取选中行 selected_items self.product_tree.selection() if not selected_items: messagebox.showwarning(提示, 请先选择要购买的商品) return # 获取数量 try: quantity int(self.quantity_var.get().strip()) if quantity 0: messagebox.showerror(错误, 购买数量必须大于0) return except ValueError: messagebox.showerror(错误, 请输入有效的数字) return # 获取选中商品 selected_item selected_items[0] product_id int(self.product_tree.item(selected_item, values)[0]) product next(p for p in PRODUCTS if p[id] product_id) # 添加到购物车 try: self.cart_service.add_to_cart(product, quantity) messagebox.showinfo(成功, f{product[name]} 已加入购物车) except ValueError as e: messagebox.showerror(错误, str(e)) def open_cart(self): 打开购物车窗体 if self.cart_window is None or not self.cart_window.winfo_exists(): self.cart_window CartWindow(self, self.cart_service) self.cart_window.lift() # 置于顶层 def logout(self): 退出登录 if messagebox.askyesno(确认, 确定要退出登录吗): self.destroy() LoginWindow().mainloop() # 购物车窗体 class CartWindow(tk.Toplevel): def __init__(self, parent, cart_service): super().__init__(parent) self.title(我的购物车) self.geometry(700x400) self.resizable(False, False) self.center_window() # 初始化数据 self.cart_service cart_service # 创建UI self.create_ui() self.update_cart() def center_window(self): 窗口居中 self.update_idletasks() width self.winfo_width() height self.winfo_height() x (self.winfo_screenwidth() // 2) - (width // 2) y (self.winfo_screenheight() // 2) - (height // 2) self.geometry(f{width}x{height}{x}{y}) def create_ui(self): 创建购物车界面 # 购物车表格 cart_frame ttk.Frame(self, padding20) cart_frame.pack(expandTrue, filltk.BOTH) # 表格列名 columns (ID, 商品名称, 单价(元), 数量, 小计(元)) self.cart_tree ttk.Treeview(cart_frame, columnscolumns, showheadings, height10) # 设置列属性 for col in columns: self.cart_tree.heading(col, textcol) self.cart_tree.column(col, width120 if col 商品名称 else 80) # 滚动条 scrollbar ttk.Scrollbar(cart_frame, orienttk.VERTICAL, commandself.cart_tree.yview) self.cart_tree.configure(yscrollcommandscrollbar.set) # 布局表格 self.cart_tree.pack(sidetk.LEFT, expandTrue, filltk.BOTH) scrollbar.pack(sidetk.RIGHT, filltk.Y) # 底部操作区 bottom_frame ttk.Frame(self, padding0 20 20 20) bottom_frame.pack(filltk.X, anchortk.E) # 总价显示 self.total_var tk.StringVar(value总计¥0.00) total_label ttk.Label(bottom_frame, textvariableself.total_var, font(微软雅黑, 12, bold)) total_label.pack(sidetk.LEFT, padx20) # 操作按钮 clear_btn ttk.Button(bottom_frame, text清空购物车, commandself.clear_cart) clear_btn.pack(sidetk.LEFT, padx10) checkout_btn ttk.Button(bottom_frame, text结算下单, commandself.checkout) checkout_btn.pack(sidetk.LEFT) def update_cart(self): 更新购物车数据 # 清空表格 for item in self.cart_tree.get_children(): self.cart_tree.delete(item) # 加载购物车数据 cart_items self.cart_service.get_cart_items() for product, quantity in cart_items: subtotal product[price] * quantity self.cart_tree.insert(, tk.END, values( product[id], product[name], f{product[price]:.2f}, quantity, f{subtotal:.2f} )) # 更新总价 total self.cart_service.calculate_total() self.total_var.set(f总计¥{total:.2f}) def clear_cart(self): 清空购物车 if self.cart_service.is_empty(): messagebox.showinfo(提示, 购物车已为空) return if messagebox.askyesno(确认, 确定要清空购物车吗): self.cart_service.clear_cart() self.update_cart() messagebox.showinfo(成功, 购物车已清空) def checkout(self): 结算下单 if self.cart_service.is_empty(): messagebox.showerror(错误, 购物车为空无法结算) return total self.cart_service.calculate_total() if messagebox.askyesno(结算确认, f确认下单\n订单总金额¥{total:.2f}): messagebox.showinfo(下单成功, f订单创建成功\n支付金额¥{total:.2f}\n感谢您的购买) self.cart_service.clear_cart() self.update_cart() self.destroy() # 关闭购物车 # 程序入口 if __name__ __main__: # 设置tkinter字体解决中文显示问题 try: tk.font.nametofont(TkDefaultFont).configure(family微软雅黑, size10) except: pass # 启动登录窗口 app LoginWindow() app.mainloop()四、运行说明4.1 运行环境Python 版本Python3.6 及以上TkinterPython 自带库无需 pip 安装第三方包如果 Linux 运行报错sudo apt install python3-tk4.2 运行步骤将全部代码复制保存为 e_shop.py直接运行脚本在登录界面输入测试账号密码登录在商品列表选中商品输入购买数量点击加入购物车点击我的购物车打开弹窗可以查看、清空、结算订单退出登录回到登录页面五、核心模块讲解5.1 CartService 购物车服务类业务逻辑层和界面解耦。add_to_cart() 添加商品到购物车重复商品累加数量calculate_total() 使用 decimal 计算总价规避浮点数精度问题clear_cart() 清空购物车后续如果改成数据库版本只需要修改这个类GUI 代码几乎不用改动。5.2 登录窗口 LoginWindow程序入口窗口校验用户名密码登录成功销毁自己打开主窗口 MainWindow。5.3 MainWindow 商品主界面使用ttk.Treeview表格组件展示全部商品选中商品设置数量加入购物车可以唤起购物车子窗口支持退出登录。5.4 CartWindow 购物车子窗口继承tk.Toplevel属于模态子弹窗实时渲染购物车列表计算小计、总金额实现清空购物车、下单结算。六、项目不足与扩展方向本项目内存存储关闭程序所有数据丢失可以扩展JSON 文件持久化保存用户、商品、订单数据新增用户注册功能购物车支持单独删除某一件商品订单历史记录查看商品分类筛选搜索框管理员后台新增、修改、删除商品对接 SQLite 数据库替代内存模拟数据七、总结本电商系统基于 Tkinter 图形化开发代码结构清晰面向对象设计适合课程设计学习。完整实现登录、商品浏览、购物车、下单整套电商基础流程没有复杂依赖开箱即用。