import tkinter as tk import DataB import Record from datetime import datetime from PIL import Image, ImageTk import tkinter.messagebox from tkinter import ttk # 一、界面类 class Windows: # 01存放用户信息的列表 user_info = [] # 01.初始化 def __init__(self, master=None): self.atm = ATM() # ATM功能类 self.master = master self.login() # 选择银行卡 self.pwd_judge = 0 # 密码验证 # 02 加载背景图像 def loadImage(self, width, height, bgt): # 使用Pillow加载图像 self.background_image = Image.open(bgt) # 这里可以使用 JPG 格式 self.background_image = self.background_image.resize((width, height), Image.Resampling.NEAREST) # 可选:调整图像大小 self.background_image = ImageTk.PhotoImage(self.background_image) # 创建一个Label来显示图像 self.background_label = tk.Label(self.root1, image=self.background_image) self.background_label.place(relwidth=1, relheight=1) # 03 程序入口 def login(self): self.root1 = tk.Frame(self.master) w = 680 h = 450 self.root1['width'] = w self.root1['height'] = h # 得到屏幕宽度和高度 sw = root.winfo_screenwidth() # 得到屏幕高度 sh = root.winfo_screenheight() # 窗口居中 x = (sw - w) / 2 y = (sh - h) / 2 root.geometry('%dx%d+%d+%d' % (w, h, x, y)) # 加载背景图像 self.loadImage(680, 450, 'image/back.jpg') self.lableFrameName = tk.Label(self.root1, text='欢迎来到模拟ATM系统', font=('微软雅黑', 20)) self.lableFrameName.place(x=200, y=50) self.btn1 = tk.Button(self.root1, text='注册', font=('微软雅黑', 18), width=8, command=self.apply) self.btn1.place(x=270, y=150) # 登录按钮 self.btn2 = tk.Button(self.root1, text='登录', font=('微软雅黑', 18), width=8, command=self.choose_card) self.btn2.place(x=270, y=250) self.root1.pack() # 04 注册窗口 def apply(self): if self.root1: self.root1.destroy() self.master.geometry("680x450") self.root1 = tk.Frame(self.master) self.root1['width'] = 680 self.root1['height'] = 450 # 加载背景图像 self.loadImage(680, 450, 'image/bg.jpg') # 身份证号码 self.labelIdName = tk.Label(self.root1, text='身份证:', font=('微软雅黑', 18)) self.labelIdName.place(x=150, y=60, anchor='e') self.varIdName = tk.StringVar(self.root1, value='') self.entryIdName = tk.Entry(self.root1, font=('微软雅黑', 18), width=25, textvariable=self.varIdName) self.entryIdName.place(x=180, y=60, anchor='w') self.entryIdName.focus_set() # 获得焦点 # 账号 self.labelUserName = tk.Label(self.root1, text='账 号:', font=('微软雅黑', 18)) self.labelUserName.place(x=150, y=120, anchor='e') self.varUserName = tk.StringVar(self.root1, value='') self.entryUserName = tk.Entry(self.root1, font=('微软雅黑', 18), width=25, textvariable=self.varUserName) self.entryUserName.place(x=180, y=120, anchor='w') self.entryUserName.focus_set() # 获得焦点 # 密码 self.labelPwd = tk.Label(self.root1, text='密 码:', font=('微软雅黑', 18)) # justify=RIGHT,anchor='w',width=80) self.labelPwd.place(x=150, y=180, anchor='e') # grid(column=0,row=1,pady=10) self.varPwd = tk.StringVar(self.root1, value='') self.entryPwd = tk.Entry(self.root1, show='*', font=('微软雅黑', 18), width=25, textvariable=self.varPwd) self.entryPwd.place(x=180, y=180, anchor='w') # grid(column=1,row=1,pady=10) # 注册按钮 self.btnz = tk.Button(self.root1, text='注册', font=('微软雅黑', 18), width=8, command=self.Jlogin) self.btnz.place(x=180, y=250) # 登录按钮 self.btnf = tk.Button(self.root1, text='登录', font=('微软雅黑', 18), width=8, command=self.choose_card) self.btnf.place(x=350, y=250) self.root1.pack() # 05 判断是否注册成功 def Jlogin(self): name = self.entryUserName.get() pwd = self.entryPwd.get() id = self.entryIdName.get() if id == '': tk.messagebox.showinfo('提示', '身份证不能为空') elif len(name) != 6: tk.messagebox.showinfo('提示', '账号必须为6位的数字或字符') elif len(pwd) < 6: tk.messagebox.showinfo('提示', '密码不能小于6位') elif id != '' and len(name) == 6 and len(pwd) >= 6: self.flag = True for x in DataB.a: if x[0] == name: self.flag = False tk.messagebox.showinfo('提示', '该账户已存在,请重新注册!') if self.flag: DataB.insert_data(name, pwd, id) self.atm.Card.append([name, pwd, 0.00, '', 0, id]) tk.messagebox.showinfo('提示', '注册成功') self.root1.destroy() self.login() # 06 返回程序入口 def Flogin(self): self.root1.destroy() self.login() # 07 选择银行卡 def choose_card(self): if self.root1: self.root1.destroy() self.master.geometry("680x450") self.root1 = tk.Frame(self.master) self.root1['width'] = 680 self.root1['height'] = 450 # 加载背景图像 self.loadImage(680, 450, 'image/bg11.jpg') # 返回注册按钮 self.btnfs = tk.Button(self.root1, text='注册', font=('微软雅黑', 11), width=8, command=self.apply) self.btnfs.place(x=0, y=0) self.lbl1 = tk.Label(self.root1, text='选择银行卡账号:', font=('microsoft yahei', 18)) self.lbl1.place(x=20, y=150) self.cbox1 = ttk.Combobox(self.root1,width=25,font=('microsoft yahei', 18)) self.cbox1['values'] = self.atm.choose_card() self.cbox1.place(x=220, y=150) self.btnc = tk.Button(self.root1, text='确认', font=('microsoft yahei', 12), command=lambda: self.confirm(self.cbox1.get())) self.btnc.place(x=600, y=150) self.root1.pack() # 08 确认选择银行卡 def confirm(self, user): if user != '': self.root1.destroy() self.master.geometry("680x450") self.root1 = tk.Frame(self.master) self.root1['width'] = 680 self.root1['height'] = 450 # 加载背景图像 self.loadImage(680, 450, 'image/bg5.jpg') # 返回按钮 self.btnfc = tk.Button(self.root1, text='返回', font=('微软雅黑', 11), width=8, command=self.Fchoose) self.btnfc.place(x=0, y=0) self.lbl2 = tk.Label(self.root1, text='账号: ' + user , font=('microsoft yahei', 15), width=30, anchor='w', justify='left') self.lbl2.place(x=20, y=150) self.lbl3 = tk.Label(self.root1, text='密码:', font=('microsoft yahei', 15)) self.lbl3.place(x=20, y=200) self.entry1 = tk.Entry(self.root1, show="*", font=('微软雅黑', 15), width=24) self.entry1.place(x=90, y=200) self.btnq = tk.Button(self.root1, text='确认', font=('microsoft yahei', 15), width=10, command=lambda: self.T_F(user, self.entry1.get())) self.btnq.place(x=120, y=260) self.root1.pack() else: tkinter.messagebox.showinfo('提示', '请选择银行卡号!') # 09.登录密码验证 def T_F(self, user, pwd): self.flag = False for i in self.atm.Card: if i[0] == user: Windows.user_info = i if i[4] == 1: tkinter.messagebox.showinfo('提示', '银行卡已冻结,请带上身份证前往柜台解锁!') exit() if i[1] == pwd and i[4] == 0: self.flag = True break if self.flag: self.c_to_f() elif self.pwd_judge == 4: self.atm.card_lock(user) tkinter.messagebox.showinfo('提示', '密码错误5次,银行卡已冻结,请带上身份证前往柜台解锁!') self.choose_card() else: self.pwd_judge += 1 tkinter.messagebox.showinfo('提示', '密码错误!你还有{0}次机会'.format(5 - self.pwd_judge)) # 10 登录成功跳转 def c_to_f(self): tkinter.messagebox.showinfo('提示', '验证通过,即将进入ATM系统!') self.root1.destroy() self.function_board() # 11.功能界面设计 def function_board(self): if self.root1: self.root1.destroy() self.master.geometry("680x450") self.root1 = tk.Frame(self.master) self.root1['width'] = 680 self.root1['height'] = 450 # 加载背景图像 self.loadImage(680, 450, 'image/bg4.jpg') self.buttons = [["查询余额", "存款", "取款", "办理其他业务"], ["转账", "查看流水", "修改密码","退卡"]] for r in range(2): for c in range(4): def cmd(key=self.buttons[r][c]): self.click(key) self.B = tk.Button(self.root1, text=self.buttons[r][c], font=('microsoft yahei', 15), width=10, bg="#C0C0C0", command=cmd) self.B.place(x=r * 150 + 200, y=c * 55 + 100) self.root1.pack() # 12 点击按钮,执行相应功能 def click(self, key): self.root1.destroy() if key == '查询余额': self.Fscreen() self.lbl4 = tk.Label(self.root1, text='卡内余额:' + str(Windows.user_info[2]), width=25,anchor='w', justify='left', font=('microsoft yahei', 20)) self.lbl4.place(x=120, y=140) self.btn3 = tk.Button(self.root1, text='返回', font=('microsoft yahei', 15), width=10, command=self.function_board) self.btn3.place(x=0, y=0) elif key in ('存款', '取款'): self.Fscreen() self.lbl4 = tk.Label(self.root1, text='输入' + key + '金额:', font=('microsoft yahei', 15)) self.lbl4.place(x=90, y=100) self.entry2 = tk.Entry(self.root1, font=('microsoft yahei', 15)) self.entry2.place(x=250, y=100) self.btn3 = tk.Button(self.root1, text='确认', width=15, command=lambda: self.atm.add_decrease_money (Windows.user_info[0], self.entry2.get(), key)) self.btn3.place(x=180, y=200) elif key == '查看流水': self.Fscreen() self.lbl4 = tk.LabelFrame(self.root1, text='流水记录') self.lbl4.place(x=50, y=60) self.text = tk.Text(self.lbl4, bg='white', height=24, width=80) self.text.insert(0.0, Windows.user_info[3]) self.text.pack() elif key == '转账': self.Fscreen() self.lbl1 = tk.Label(self.root1, text='转入卡的账号:',width=12, font=('microsoft yahei', 18)) self.lbl1.place(x=20, y=150) self.cbox1 = ttk.Combobox(self.root1, width=20,font=('microsoft yahei', 18)) self.cbox1['values'] = self.atm.choose_card() self.cbox1.place(x=220, y=150) self.lbl2 = tk.Label(self.root1, text='转账金额:', width=12, font=('microsoft yahei', 18), anchor='w', justify='left') self.lbl2.place(x=20, y=220) self.entry2 = tk.Entry(self.root1,width=20,font=('microsoft yahei', 18)) self.entry2.place(x=220, y=220) self.btn1 = tk.Button(self.root1, text='确认', width=10, font=('microsoft yahei', 18), command=lambda: self.atm.to_user (Windows.user_info[0], self.cbox1.get(), self.entry2.get())) self.btn1.place(x=260, y=350) elif key == "修改密码": self.Fscreen() # 输入旧密码 self.labelOldPwd = tk.Label(self.root1, text='输入旧密码:', font=('微软雅黑', 18)) # justify=RIGHT,anchor='w',width=80) self.labelOldPwd.place(x=150, y=90, anchor='e') # grid(column=0,row=1,pady=10) self.varOldPwd = tk.StringVar(self.root1, value='') self.entryOldPwd = tk.Entry(self.root1, show='*', font=('微软雅黑', 18), width=25, textvariable=self.varOldPwd) self.entryOldPwd.place(x=180, y=90, anchor='w') # grid(column=1,row=1,pady=10) # 输入新密码 self.labelNewPwd = tk.Label(self.root1, text='输入新密码:', font=('微软雅黑', 18)) # justify=RIGHT,anchor='w',width=80) self.labelNewPwd.place(x=150, y=160, anchor='e') # grid(column=0,row=1,pady=10) self.varNewPwd = tk.StringVar(self.root1, value='') self.entryNewPwd = tk.Entry(self.root1, show='*', font=('微软雅黑', 18), width=25, textvariable=self.varNewPwd) self.entryNewPwd.place(x=180, y=160, anchor='w') # grid(column=1,row=1,pady=10) self.btnz = tk.Button(self.root1, text='确认修改', font=('微软雅黑', 18), width=8, command=lambda: self.atm.Change(Windows.user_info[0], self.entryOldPwd.get(), self.entryNewPwd.get())) self.btnz.place(x=220, y=250) elif key=="办理其他业务": self.Fscreen() self.lblq = tk.Label(self.root1, text='如需办理其他业务,请移步柜台咨询!' , width=30, anchor='w', justify='left', font=('microsoft yahei', 20)) self.lblq.place(x=120, y=140) else: self.root1.destroy() tk.messagebox.showinfo('提示', '感谢您的使用,请收好您的银行卡!') self.choose_card() def Fscreen(self): self.root1 = tk.Frame(self.master) self.root1['width'] = 680 self.root1['height'] = 450 # 加载背景图像 self.loadImage(680, 450, 'image/function.jpg') # 左上角返回按钮 self.btn3 = tk.Button(self.root1, text='返回', font=('microsoft yahei', 15), width=10, command=self.function_board) self.btn3.place(x=0, y=0) self.root1.pack() # 返回银行卡选择界面 def Fchoose(self): self.root1.destroy() self.choose_card() class ATM: # 01初始化参数 def __init__(self): # 存放账户的列表 self.Card = [] self.read_card() # 02读卡功能 def read_card(self): DataB.select_data() for x in DataB.a: self.Card.append(x) # 列表中存放的元素还是列表 # 02 锁卡功能, 不会用,搞不明白,重写 def card_lock(self, user): for i in self.Card: if i[0] == user: i[4] = 1 break self.update_Card() # 03 增加账号,注册办卡, 可以删除 def insert_card(self, user, pwd): self.flag = True for x in DataB.a: if x[0] == user: self.flag = False tk.messagebox.showinfo('提示', '该账户已存在,请重新注册!') if self.flag: DataB.insert_data(user, pwd) tk.messagebox.showinfo('提示', '注册成功') # 04获取时间 def timeNow(self): # 获取当前时间 now = datetime.now() # 将时间转换为字符串,返回当前时间 formatted_time = f"{now:%Y年%m月%d日 %H:%M:%S}" return formatted_time # 05存款取款操作 def add_decrease_money(self, user, money, key): if money == '': tk.messagebox.showinfo('提示', '请输入金额') else: if key == '存款': for i in self.Card: if i[0] == user: i[2] += int(money) Record.insert_data(user,ATM.timeNow(self),f'存入了{money}元',i[2]) i[3] += '你在{0}存入了{1}元,现有余额为{2}\n'.\ format(ATM.timeNow(self), money, i[2]) break tk.messagebox.showinfo('提示', '存入成功') self.update_Card() else: # 取款 for i in self.Card: if i[0] == user: i[2] -= int(money) if i[2] > 0: Record.insert_data(user,ATM.timeNow(self),f'取出了{money}元',i[2]) i[3] += '你在{0}取出了{1}元,现有余额为{2}\n'. \ format(ATM.timeNow(self), money, i[2]) tk.messagebox.showinfo('提示', '取出成功') break else: tk.messagebox.showinfo('提示', '余额不足') i[2] += int(money) break self.update_Card() #06 转账功能 def to_user(self, user1, user2, money): if money == '': tk.messagebox.showinfo('提示', '请输入金额') elif user1 == user2: tk.messagebox.showinfo('提示', '操作失败,转入的是本账号') else: self.flag = True for i in self.Card: if i[0] == user1: i[2] -= int(money) if i[2] < 0: tk.messagebox.showinfo('提示', '余额不足') i[2] += int(money) self.flag = False break Record.insert_data(user1, ATM.timeNow(self),f'向"{user2}"账户转出了{money}元',i[2]) i[3] += '你在{0}向“{1}”账户转出了{2}元,现有余额为{3}\n'. \ format(ATM.timeNow(self), user2, money, i[2]) break if self.flag: for i in self.Card: if i[0] == user2: i[2] += int(money) Record.insert_data(user2, ATM.timeNow(self),f'收到了来自账户“{user1}”转入的{money}元',i[2]) i[3] += '你在{0}收到了账户“{1}”转入的{2}元,现有余额为{3}\n'. \ format(ATM.timeNow(self),user1, money, i[2]) tk.messagebox.showinfo('提示', '转账成功') self.update_Card() # 05 修改密码 def Change(self, user, oldP, newP): for i in self.Card: if i[0] == user: if i[1] == oldP and len(newP) >= 6: i[1] = newP tk.messagebox.showinfo('提示', '密码修改成功') self.update_Card() break elif len(newP)< 6: tk.messagebox.showinfo('提示', '新密码不能小于6位') else: tk.messagebox.showinfo('提示', '旧密码输入错误') # 06更新数据 def update_Card(self): for i in self.Card: DataB.update_data(i[0], i[1],i[2], i[3], i[4], i[5]) # 07选择银行卡 def choose_card(self): return [i[0] for i in self.Card] if __name__ == '__main__': root = tk.Tk() root.title('Python ATM系统-bhml') root.resizable(width=False, height=False) app = Windows(root) root.mainloop()