|
|
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() |