概述
这是本人用Python Tkinter做的一个登录程序,因为连接了SQL数据库,所以需要新建一个“账号登录”数据库,创建一张“登录注册”表,然后再编写代码运行。里面有详细的注释说明,对于有一定基础知识的同学来说比较友好。
期间我发现了很多问题所在,控件框架布局基本不变,主要是功能实现方法,反反复复修改了很多次,吸取了很多经验教训。
数据库连接信息,用SQL Server身份验证登录,记住登录名和密码。
新建一个“账号登录”数据库,在里面创建一张“登录注册表”,设置好列名username、password和数据类型。
输入的密码采用了MD5加盐加密操作,所以password一栏显示为密文。
然后就是python窗体源代码了,我这里创建了5个Form窗体,包含了账号登录、账号注册、修改密码、账号注销四个功能。虽然这些功能函数和控件是相关联的,这里我还是拆分解析一下各部分代码功能。
我们首先来连接一下SQL Server数据库,记得要导入相关的安装包
import pymssql
# 数据库连接
conn = pymssql.connect('服务器名称', '登录名', '密码', '数据库名称', )
#例如:conn = pymssql.connect('WSDFERESQLEXPRESS', 'sa', '1234567890, '账号登录', )
## windows本地身份验证登录:conn = pymssql.connect(server='服务器名称', database='数据库名称')
if conn:
print("数据库连接成功!")
else:
print("数据库连接失败!")
cur = conn.cursor()
#创建一个游标对象,在函数里面调用,在运行过程中不能断开连接,否则会报错。直到关闭窗口时再关闭游标对象和数据库对象连接。
再来创建第1个窗体Form1
# 窗体居中显示
def Center(winform):
winform.config(background="#C0C0C0")
width = winform.winfo_screenwidth() # 获取屏幕宽度
height = winform.winfo_screenheight() # 获取屏幕高度
winform.resizable(False, False) # 窗体固定尺寸
winform.geometry("%dx%d+%d+%d" % (width / 2.0, height / 2.0, width / 4.0, height / 4.0))
Form1 = tkinter.Tk() # 创建一个窗体Form1
Form1.title('登录界面') #设置窗体标题
#调用Center方法实现窗体居中
Center(Form1) # 窗体Form1居中显示
# protocol是一个创建销毁窗口的方法,绑定Exit()函数以后,在任意一个窗口右上方点击“X”后都能直接退出并关闭所有窗体后台程序
Form1.protocol("WM_DELETE_WINDOW", Exit) # 点击右上方的“X”后退出所有窗体程序
以此类推,再创建其他4个窗体
# 窗体居中显示
def Center(winform):
winform.config(background="#C0C0C0")
width = winform.winfo_screenwidth() # 获取屏幕宽度
height = winform.winfo_screenheight() # 获取屏幕高度
winform.resizable(False, False) # 窗体固定尺寸
winform.geometry("%dx%d+%d+%d" % (width / 2.0, height / 2.0, width / 4.0, height / 4.0))
# 主程序代码
Form1 = tkinter.Tk() # 创建一个窗体Form1
Form2 = tkinter.Tk() # 创建一个窗体Form2
Form3 = tkinter.Tk() # 创建一个窗体Form3
Form4 = tkinter.Tk() # 创建一个窗体Form4
Form5 = tkinter.Tk() # 创建一个窗体Form5
#设置各窗体标题
Form1.title('登录界面')
Form2.title("主界面")
Form3.title("注册界面")
Form4.title("修改密码")
Form5.title("账号注销")
#调用Center()方法使窗体居中显示
Center(Form1) # 窗体Form1居中显示
Center(Form2) # 窗体Form2居中显示
Center(Form3) # 窗体Form3居中显示
Center(Form4) # 窗体Form4居中显示
Center(Form5) # 窗体Form5居中显示
# 一次性创建5个窗体后,需要用withdraw()来隐藏其他窗口,只显示一个登录窗口Form1
Form2.withdraw() # 隐藏窗体Form2
Form3.withdraw() # 隐藏窗体Form3
Form4.withdraw() # 隐藏窗体Form4
Form5.withdraw() # 隐藏窗体Form5
# protocol是一个创建销毁窗口的方法,绑定Exit()函数以后,在任意一个窗口右上方点击“X”后都能直接退出并关闭所有窗体后台程序
Form1.protocol("WM_DELETE_WINDOW", Exit) # 点击右上方的“X”后退出所有窗体程序
Form2.protocol("WM_DELETE_WINDOW", Exit)
Form3.protocol("WM_DELETE_WINDOW", Exit)
Form4.protocol("WM_DELETE_WINDOW", Exit)
Form5.protocol("WM_DELETE_WINDOW", Exit)
Form5.mainloop()
Form4.mainloop()
Form3.mainloop()
Form2.mainloop()
Form1.mainloop()
窗体Form1(登录界面)的相关控件代码
label1 = Label(Form1, text="账号", bg="#C0C0C0", font=('微软雅黑', 18), bd=5, relief='flat', justify="center", )
label1.place(x=200, y=100)
#label1控件在Form1上面,文本显示为“账号”,十六进制背景颜色,18号微软雅黑字体,边框宽度为5px,默认样式,文本居中显示。
#label1控件位置距离窗体左边框200px,距离上边框100px.
label2 = Label(Form1, text="密码", bg="#C0C0C0", font=('微软雅黑', 18), bd=5, relief='flat', justify="center")
label2.place(x=200, y=215)
text1 = tkinter.Entry(Form1, font=("微软雅黑", 17), relief="flat", width=28, borderwidth=5, justify="center")
text1.place(x=350, y=105)
#Entry控件text1在Form1上面,17号微软雅黑字体,默认样式,宽度为28px,边框宽度为5px,文本居中显示。
#text1控件位置距离窗体左边框350px,距离上边框105px.
text2 = tkinter.Entry(Form1, font=("微软雅黑", 17), show="*", relief="flat", width=28, borderwidth=5, justify="center")
text2.place(x=350, y=220)
text1.focus() # 鼠标光标定位在文本输入框text1上面
button1 = Button(Form1, text="登录", relief='flat', font=('黑体', 17), padx=15, pady=5, command=Login, )
button1.place(x=330, y=370)
#Button控件button1在Form1上面,文本显示为“登录”,默认样式,17号黑体字体,文本与边框的水平距离和垂直距离(即内边距)为15px和5px,调用的函数方法Login():登录功能
button2 = Button(Form1, text="重置", relief='flat', font=('黑体', 17), padx=15, pady=5, command=Clear1, )
button2.place(x=750, y=370)
#调用的函数为Clear1():重置Form1输入信息
button3 = Button(Form1, text="注册", relief='flat', font=('黑体', 17), padx=15, pady=5, command=lambda: Form(3), )
button3.place(x=330, y=500)
#调用带参数的函数Form(*args):跳转注册界面
button4 = Button(Form1, text="退出", relief='flat', font=('黑体', 17), padx=15, pady=5, command=Exit)
button4.place(x=750, y=500)
#调用的函数为Exit():退出所有窗体程序和进程
窗体Form3(注册界面)相关的控件代码
label11 = Label(Form3, text="注册账号", bg="#C0C0C0", font=('微软雅黑', 18), bd=5, relief='flat', justify="center")
label11.place(x=140, y=100)
#Label控件label11在Form3上面,文本显示为“注册账号”,十六进制背景颜色,18号微软雅黑字体,边框宽度为5px,默认样式,文本居中显示。
#label11的位置距离窗体左边框140px,距离上边框100px。
label12 = Label(Form3, text="输入密码", bg="#C0C0C0", font=('微软雅黑', 18), bd=5, relief='flat', justify="center")
label12.place(x=140, y=200)
label13 = Label(Form3, text="确认密码", bg="#C0C0C0", font=('微软雅黑', 18), bd=5, relief='flat', justify="center")
label13.place(x=140, y=300)
text11 = tkinter.Entry(Form3, font=("微软雅黑", 17), relief="flat", borderwidth=5, width=28, justify="center")
text11.place(x=380, y=105)
text12 = tkinter.Entry(Form3, font=("微软雅黑", 17), relief="flat", show="*", borderwidth=5, width=28, justify="center")
text12.place(x=380, y=205)
text13 = tkinter.Entry(Form3, font=("微软雅黑", 17), relief="flat", show='*', borderwidth=5, width=28, justify="center")
text13.place(x=380, y=305)
button11 = Button(Form3, text="确定", relief='groove', font=('黑体', 17), padx=15, pady=5, command=Register)
button11.place(x=250, y=450)
#button11调用了Register()函数:注册功能。
button12 = Button(Form3, text="重置", relief='groove', font=('黑体', 17), padx=15, pady=5, command=Clear3)
button12.place(x=550, y=450)
#button12调用了Clear3()方法,重置Form3界面输入的信息。
button13 = Button(Form3, text="取消", relief='groove', font=('黑体', 17), padx=15, pady=5, command=lambda: Form(1))
button13.place(x=850, y=450)
#button13调用了带参数的函数方法Form(3):跳转登录界面Form1。
窗体Form2(主界面)的相关控件代码
button21 = Button(Form2, text="退出", relief='flat', font=('黑体', 17), padx=15, pady=5, command=Exit)
button21.place(x=750, y=600)
button22 = Button(Form2, text="修改密码", relief="flat", font=("黑体", 17), padx=15, pady=5, command=lambda: Form(4))
button22.place(x=250, y=450)
button23 = Button(Form2, text="账号注销", relief="flat", font=("黑体", 17), padx=15, pady=5, command=lambda: Form(5), )
button23.place(x=680, y=450)
button24 = Button(Form2, text="返回", relief="flat", font=("黑体", 17), padx=15, pady=5, command=reForm1, )
button24.place(x=320, y=600)
label21 = tkinter.Label(Form2, text="账号:", font=("微软雅黑", 18), padx=10, pady=10, bg="#C0C0C0", relief="flat", justify="center", )
label21.place(x=100, y=60)
label22 = tkinter.Label(Form2, text=text1.get(), font=("微软雅黑", 18), padx=10, pady=10, bg="#C0C0C0", relief="flat", justify="left", )
label22.place(x=250, y=60)
** 窗体Form4(修改密码)界面相关的窗体代码**
label32 = Label(Form4, text="旧密码", bg="#C0C0C0", font=('微软雅黑', 18), bd=5, relief='flat', justify="center")
label32.place(x=180, y=200)
label33 = Label(Form4, text="新密码", bg="#C0C0C0", font=('微软雅黑', 18), bd=5, relief='flat', justify="center")
label33.place(x=180, y=300)
text32 = tkinter.Entry(Form4, font=("微软雅黑", 17), relief="flat", borderwidth=5, width=28, justify="center")
text32.place(x=380, y=205)
text33 = tkinter.Entry(Form4, font=("微软雅黑", 17), show='*', relief="flat", borderwidth=5, width=28, justify="center")
text33.place(x=380, y=305)
button31 = Button(Form4, text="确定", relief='groove', font=('黑体', 17), padx=15, pady=5, command=Change)
button31.place(x=250, y=450)
button32 = Button(Form4, text="重置", relief='groove', font=('黑体', 17), padx=15, pady=5, command=Clear4)
button32.place(x=550, y=450)
button33 = Button(Form4, text="取消", relief='groove', font=('黑体', 17), padx=15, pady=5, command=lambda: Form(2))
button33.place(x=850, y=450)
窗体Form5(账号注销)界面的相关控件代码
label41 = Label(Form5, text="账号密码", bg="#C0C0C0", font=('微软雅黑', 18), bd=5, relief='flat', justify="center")
label41.place(x=120, y=205)
text41 = tkinter.Entry(Form5, font=("微软雅黑", 17), relief="flat", borderwidth=5, width=28, justify="center")
text41.place(x=350, y=205)
button41 = Button(Form5, text="注销", relief='groove', font=('黑体', 17), padx=15, pady=5, command=Cancel, )
button41.place(x=280, y=350)
button42 = Button(Form5, text="重置", relief='groove', font=('黑体', 17), padx=15, pady=5, command=Clear5, )
button42.place(x=565, y=350)
button43 = Button(Form5, text="取消", relief='groove', font=('黑体', 17), padx=15, pady=5, command=lambda: Form(2), )
button43.place(x=850, y=350)
MD5加盐加密方法:
# MD5加盐加密操作
def Encrypt(SaltPwd):
obj = hashlib.md5(SaltPwd.encode("utf-8"))
obj.update(SaltPwd.encode("utf-8"))
return obj.hexdigest()
然后是相关的函数功能实现,账号登录功能方法:Login()
def Login():
user = text1.get().strip() # 输入的账号
pwd = text2.get().strip() # 输入的密码
CipherText = Encrypt(user + pwd) # 对账号和密码进行MD5加盐加密操作后的密文,用来验证账号密码是否正确,注册的时候密码pwd也是以密文形式存储的
sql = 'select count(*) from 登录注册表 where username=%s '
cur.execute(sql, (user,)) # 通过筛选输入的账号来判断账号是否存在,
result = cur.fetchone()
if user == "":
tkinter.messagebox.showinfo("提示", "用户名不得为空!")
text1.focus()
elif pwd == "":
tkinter.messagebox.showinfo("提示", "密码不得为空!")
text2.focus()
elif result[0] == True: # 如果读取到了一条返回值,则说明账号存在;然后再判断密码是否正确
sql2 = 'select password from 登录注册表 where username=%s '
cur.execute(sql2, (user,)) # 通过SQL语句筛选‘输入账号user’的密码返回值
result2 = cur.fetchone() # 获取返回的密码(返回一条记录)
if result2[0] == CipherText: # 如果密文等于返回值密码,则登录成功
tkinter.messagebox.showinfo("提示", "登录成功!")
label22["text"] = user # 登录成功后,输入账号user的值会显示在住界面Form2的label22上面
Clear1()
Form(2) # 跳转主界面Form2
else:
tkinter.messagebox.showinfo("提示", "密码错误!")
text2.delete(0, tkinter.END)
else: # 没有读取到返回值记录
messbox = tkinter.messagebox.askyesno("提示", "账号不存在,是否选择注册一个新账号?")
if messbox == YES:
Clear1()
Form(3)
else:
Clear1()
text1.focus()
账号注册功能方法:Register()
# 界面Form3:注册功能
def Register():
newuser = text11.get().strip() # 注册账号
newpwd = text12.get().strip() # 注册账号密码
renewpwd = text13.get().strip() # 确认账号密码
CipherText = Encrypt(newuser + newpwd) # 对账号和密码进行加盐加密后的密文
sql = 'select count(*) from 登录注册表 where username=%s'
cur.execute(sql, (newuser,))
result = cur.fetchone() # 获取返回值(返回一条记录)
if newuser == "":
tkinter.messagebox.showinfo("提示", "注册账号不得为空!")
text11.focus()
elif newpwd == "":
tkinter.messagebox.showinfo("提示", "注册账号密码不得为空!")
text12.focus()
elif newpwd != renewpwd:
tkinter.messagebox.showinfo("提示", "两次密码不一致,请重新输入密码!")
text13.delete(0, tkinter.END)
text13.focus()
elif result[0] == True: #获取到一条返回值,则说明账号已存在
tkinter.messagebox.askyesno("提示", "该账号已注册!请重新注册!")
Clear3()
else:
tkinter.messagebox.showinfo("提示", "新账号注册成功!")
Clear3()
sql2 = "insert into 登录注册表 (username, password) values (%s, %s)"
cur.execute(sql2, (newuser, CipherText,)) # 将游标对象cur关联sql2语句,保存注册后的账号信息(密码以密文的形式保存),登录功能也是通过密文来判断账号密码是否正确
conn.commit() # 提交sql2语句到SQL数据库,并执行该语句,查询语句不需要commit()
Form(1) # 返回登录界面Form1
修改密码功能函数:Change()
# 界面4:修改账号密码
def Change():
user = label22["text"] # 窗体Form2显示的账号
oldpwd = text32.get().strip() # 旧密码
newpwd = text33.get().strip() # 新密码
CipherText1 = Encrypt(user + oldpwd) # 对账号和旧密码进行加盐加密后的密文,用来验证账号密码是否正确
CipherText2 = Encrypt(user + newpwd) # 对账号和新密码进行加盐加密后的密文,验证密码成功后将替换旧密码
sql = 'select password from 登录注册表 where username=%s '
cur.execute(sql, (user,)) # 通过user来获取返回的密码(密文形式)
result = cur.fetchone() # 获取返回值(返回一条记录)
if oldpwd == "":
tkinter.messagebox.showinfo("提示", "密码不得为空!")
text32.focus()
elif newpwd == "":
tkinter.messagebox.showinfo("提示", "请输入新密码!")
text33.focus()
elif result[0] == CipherText1:
tkinter.messagebox.showinfo("提示", "账号密码修改成功!!")
sql2 = 'update 登录注册表 set password=%s where username=%s'
cur.execute(sql2, (CipherText2, user,)) # 将游标对象cur关联sql2语句,保存修改后的账号密码(以密文的形式保存)
conn.commit() # 提交sql2语句到SQL数据库,并执行该语句,查询语句不需要使用commit()
Clear4()
Form(1) # 跳转主界面Form1,重新登录
else:
tkinter.messagebox.showinfo("提示", "账号密码错误!")
Clear4()
账号注销功能函数:Cancel()
# 界面Form5:账号注销
def Cancel():
user = label22["text"] # 这里的账号是登录成功后,主界面窗体Form2显示的账号
pwd = text41.get().strip()
CipherText = Encrypt(user + pwd) # 对账号和密码进行加盐加密后的密文
sql = 'select password from 登录注册表 where username=%s '
cur.execute(sql, (user,))
result = cur.fetchone() # 获取密码返回值(返回一条记录)
if text41.get() == "":
tkinter.messagebox.showinfo("提示", "密码不得为空!")
text41.focus()
elif result[0] == CipherText:
tkinter.messagebox.showinfo("提示", "账号注销成功!")
sql2 = 'delete from 登录注册表 where username=%s '
cur.execute(sql2, (user,)) # 从SQL数据库中删除注销后的账号信息
conn.commit() # 提交sql2语句到SQL数据库,并执行该语句,查询语句不需要使用commit()
Clear5()
Form(1) # 跳转登录界面Form1
else:
tkinter.messagebox.showinfo("提示", "账号密码错误!")
Clear5()
重置窗体输入信息的方法函数:Clear()
# 登录界面Form1输入信息重置
def Clear1(*args):
text1.delete(0, tkinter.END)
text2.delete(0, tkinter.END)
text1.focus() # 鼠标光标定位在文本输入框text1上
# 注册界面Form3输入信息重置
def Clear3(*args):
text11.delete(0, tkinter.END)
text12.delete(0, tkinter.END)
text13.delete(0, tkinter.END)
text11.focus() # 鼠标光标定位在文本输入框text11上
# 修改界面Form4输入信息重置
def Clear4(*args):
text32.delete(0, tkinter.END)
text33.delete(0, tkinter.END)
text32.focus() ##鼠标光标定位在文本输入框text31上
# 注销界面Form5输入信息重置
def Clear5():
text41.delete(0, tkinter.END)
text41.focus() ##鼠标光标定位在文本输入框text41上
*跳转窗体界面的方法函数:Form(args)
# 跳转指定界面窗体
def Form(st):
if st == 1:
# 在跳转的窗体的时候要用withdraw()来隐藏当前窗体,不能使用destroy()来关闭窗体,因为会断掉与其他窗体的数据关联,特别是在连接了数据库的情况下。
Form2.withdraw() # 隐藏窗体Form2
Form3.withdraw() # 隐藏窗体Form2
Form4.withdraw() # 隐藏窗体Form2
Form5.withdraw() # 隐藏窗体Form2
Center(Form1) # 窗体Form1居中显示
Form1.deiconify() # 窗体Form1显示
text1.focus() # 鼠标光标定位在文本输入框text1
elif st == 2:
Form1.withdraw()
Form3.withdraw()
Form4.withdraw()
Form5.withdraw()
Center(Form2)
Form2.deiconify()
elif st == 3:
Form1.withdraw()
Form2.withdraw()
Form4.withdraw()
Form5.withdraw()
Center(Form3)
Form3.deiconify()
text11.focus()
elif st == 4:
Form1.withdraw()
Form2.withdraw()
Form3.withdraw()
Form5.withdraw()
Center(Form4)
Form4.deiconify()
text32.focus()
elif st == 5:
Form1.withdraw()
Form2.withdraw()
Form3.withdraw()
Form4.withdraw()
Center(Form5)
Form5.deiconify()
text41.focus()
def reForm1():
messbox = tkinter.messagebox.askyesno("提示", "是否返回登录界面?")
if messbox == YES:
Form(1)
最后,就是完整的窗体程序源代码,我将其封装在一个类里面。其中,控件的位置用的是相对位置表示,目的是为了适应不同设备的分辨率。
import hashlib
import sys
import tkinter
import tkinter.messagebox
from tkinter import *
import pymssql
class Account:
# 数据库连接
def __init__(self):
self.__conn = pymssql.connect(server='ASEKJHFDWEK', database='账号登录') # windows本地身份验证登录
#账号密码验证 self.__conn = pymssql.connect('服务器名称', '账号', '密码', '数据库名称', )
if self.__conn:
print("数据库连接成功!")
else:
print("数据库连接失败!")
# 登录界面self.__Form1输入信息重置
def __Clear1(self):
self.__text1.delete(0, tkinter.END)
self.__text2.delete(0, tkinter.END)
self.__text1.focus() # 鼠标光标定位在文本输入框self.__text1上
# 注册界面self.__Form3输入信息重置
def __Clear3(self):
self.__text11.delete(0, tkinter.END)
self.__text12.delete(0, tkinter.END)
self.__text13.delete(0, tkinter.END)
self.__text11.focus() # 鼠标光标定位在文本输入框self.__text11上
# 修改界面self.__Form4输入信息重置
def __Clear4(self):
self.__text32.delete(0, tkinter.END)
self.__text33.delete(0, tkinter.END)
self.__text32.focus() ##鼠标光标定位在文本输入框self.__text31上
# 注销界面self.__Form5输入信息重置
def __Clear5(self):
self.__text41.delete(0, tkinter.END)
self.__text41.focus() ##鼠标光标定位在文本输入框self.__text41上
# 退出所有窗体程序运行
def __Exit(self):
self.__conn.close() # 关闭数据库连接对象
self.__Form1.quit()
self.__Form1.destroy() # 关闭窗体·self.__Form1后台运行
self.__Form2.quit()
self.__Form2.destroy()
self.__Form3.quit()
self.__Form3.destroy()
self.__Form4.quit()
self.__Form4.destroy()
self.__Form5.quit()
self.__Form5.destroy()
sys.exit(0)
# 窗体居中显示
def __Center(self, winform):
winform.config(background="#CFCFCF")
self.__width = winform.winfo_screenwidth() # 获取屏幕宽度
self.__height = winform.winfo_screenheight() # 获取屏幕高度
# winform.resizable(False, False) # 窗体固定尺寸
winform.geometry("%dx%d+%d+%d" % (self.__width / 2.0, self.__height / 2.0, self.__width / 4.0, self.__height / 4.0))
# protocol是一个创建销毁窗口的方法,绑定Exit()函数以后,在任意一个窗口右上方点击“X”后都能直接退出并关闭所有窗体后台程序
winform.protocol("WM_DELETE_WINDOW", self.__Exit) # 点击右上方的“X”后退出所有窗体程序
# 跳转指定界面窗体
def __Form(self, st):
if st == 1:
# 在跳转的窗体的时候要用withdraw()来隐藏当前窗体,不能使用destroy()来关闭窗体,
# 因为会断掉与其他窗体的数据关联,特别是在连接了数据库的情况下。
self.__Form2.withdraw() # 隐藏窗体self.__Form2
self.__Form3.withdraw() # 隐藏窗体self.__Form2
self.__Form4.withdraw() # 隐藏窗体self.__Form2
self.__Form5.withdraw() # 隐藏窗体self.__Form2
self.__Center(self.__Form1) # 窗体self.__Form1居中显示
self.__Form1.deiconify() # 窗体self.__Form1显示
self.__text1.focus() # 鼠标光标定位在文本输入框self.__text1
elif st == 2:
self.__Form1.withdraw()
self.__Form3.withdraw()
self.__Form4.withdraw()
self.__Form5.withdraw()
self.__Center(self.__Form2)
self.__Form2.deiconify()
elif st == 3:
self.__Form1.withdraw()
self.__Form2.withdraw()
self.__Form4.withdraw()
self.__Form5.withdraw()
self.__Center(self.__Form3)
self.__Form3.deiconify()
self.__text11.focus()
elif st == 4:
self.__Form1.withdraw()
self.__Form2.withdraw()
self.__Form3.withdraw()
self.__Form5.withdraw()
self.__Center(self.__Form4)
self.__Form4.deiconify()
self.__text32.focus()
elif st == 5:
self.__Form1.withdraw()
self.__Form2.withdraw()
self.__Form3.withdraw()
self.__Form4.withdraw()
self.__Center(self.__Form5)
self.__Form5.deiconify()
self.__text41.focus()
def __reForm1(self): # 返回登录界面self.__Form1
self.__messbox = tkinter.messagebox.askyesno("提示", "是否返回登录界面?")
if self.__messbox == YES:
self.__Form(1)
# MD5加盐加密操作
def __Encrypt(self, SaltPwd):
self.__obj = hashlib.md5(SaltPwd.encode("gbk"))
self.__obj.update(SaltPwd.encode("utf-8"))
return self.__obj.hexdigest()
# 账号登录操作
def __Login(self):
self.__cur = self.__conn.cursor()
self.__user = self.__text1.get().strip() # 输入的账号
self.__pwd = self.__text2.get().strip() # 输入的密码
self.__CipherText = self.__Encrypt(self.__user + self.__pwd) # 对账号和密码进行MD5加盐加密操作后的密文,用来验证账号密码是否正确,注册的时候密码pwd也是以密文形式存储的
self.__sql = 'select count(*) from 登录注册表 where username=%s '
self.__cur.execute(self.__sql, (self.__user,)) # 通过筛选输入的账号来判断账号是否存在
self.__result = self.__cur.fetchone()
if self.__user == "":
tkinter.messagebox.showinfo("提示", "用户名不得为空!")
self.__text1.focus()
elif self.__pwd == "":
tkinter.messagebox.showinfo("提示", "密码不得为空!")
self.__text2.focus()
elif self.__result[0] == FALSE: # 如果读取到了一条返回值,则说明账号存在;然后再判断密码是否正确
messbox = tkinter.messagebox.askyesno("提示", "账号不存在,是否选择注册一个新账号?")
if messbox == YES:
self.__Clear1()
self.__Form(3)
else:
self.__Clear1()
self.__text1.focus()
else:
self.__VerifyLogin(self.__user)
# 验证账号密码是否正确
def __VerifyLogin(self, user):
self.__cur = self.__conn.cursor()
self.__sql2 = 'select count(*) from 登录注册表 where username=%s '
self.__cur.execute(self.__sql2, (user,)) # 通过SQL语句筛选‘输入账号user’的密码返回值
self.__result2 = self.__cur.fetchone() # 获取返回的密码(返回一条记录)
if self.__result2[0] == TRUE: # 如果密文等于返回值密码,则登录成功
tkinter.messagebox.showinfo("提示", "登录成功!")
self.__label22["text"] = user # 登录成功后,输入账号user的值会显示在住界面self.__Form2的self.__label22上面
self.__Clear1()
self.__Form(2) # 跳转主界面self.__Form2
else:
tkinter.messagebox.showinfo("提示", "账号密码错误!")
self.__text2.delete(0, tkinter.END)
# 界面self.__Form3:注册功能
def __Register(self):
# 创建一个游标对象cur
self.__cur = self.__conn.cursor()
self.__user = self.__text11.get().strip() # 注册账号
self.__newpwd = self.__text12.get().strip() # 注册账号密码
self.__renewpwd = self.__text13.get().strip() # 确认账号密码
self.__CipherText = self.__Encrypt(self.__user + self.__newpwd) # 对账号和密码进行加盐加密后的密文
sql = 'select count(*) from 登录注册表 where username=%s'
self.__cur.execute(sql, (self.__user,))
self.__result = self.__cur.fetchone() # 获取返回值(返回一条记录)
if self.__user == "":
tkinter.messagebox.showinfo("提示", "注册账号不得为空!")
self.__text11.focus()
elif self.__newpwd == "":
tkinter.messagebox.showinfo("提示", "注册账号密码不得为空!")
self.__text12.focus()
elif self.__newpwd != self.__renewpwd:
tkinter.messagebox.showinfo("提示", "两次密码不一致,请重新输入密码!")
self.__text13.delete(0, tkinter.END)
self.__text13.focus()
elif self.__result[0] == True:
tkinter.messagebox.askyesno("提示", "该账号已注册!请重新注册!")
self.__Clear3()
else:
self.__SaveRegister(self.__user, self.__CipherText)
# 保存注册后的账号密码消息到数据库
def __SaveRegister(self, user, CipherText):
try:
self.__cur = self.__conn.cursor()
tkinter.messagebox.showinfo("提示", "新账号注册成功!")
sql2 = "insert into 登录注册表 (username, password) values (%s, %s)"
self.__cur.execute(sql2, (self.__user, self.__CipherText,)) # 将游标对象cur关联sql2语句,保存注册后的账号信息(密码以密文的形式保存)
self.__conn.commit() # 提交sql2语句到SQL数据库,并执行该语句,查询语句不需要commit()
self.__Clear3()
self.__Form(1) # 返回登录界面self.__Form1
except EXCEPTION as ex:
tkinter.messagebox.showinfo("提示", "账号注册失败!")
tkinter.messagebox.showinfo("提示", ex)
self.__Clear3()
self.__text11.focus()
# 界面4:修改账号密码
def __Change(self):
self.__cur = self.__conn.cursor()
self.__user = self.__label22["text"] # 账号
self.__oldpwd = self.__text32.get().strip() # 旧密码
self.__newpwd = self.__text33.get().strip() # 新密码
self.__CipherText1 = self.__Encrypt(self.__user + self.__oldpwd) # 对账号和旧密码进行加盐加密后的密文
self.__CipherText2 = self.__Encrypt(self.__user + self.__newpwd) # 对账号和新密码进行加盐加密后的密文
self.__sql = 'select count(*) from 登录注册表 where username=%s '
self.__cur.execute(self.__sql, (self.__user,)) # 将游标对象cur关联sql语句,判断账号和密码是否正确
self.__result = self.__cur.fetchone() # 获取返回值(返回一条记录)
if self.__oldpwd == "":
tkinter.messagebox.showinfo("提示", "密码不得为空!")
self.__text32.focus()
elif self.__newpwd == "":
tkinter.messagebox.showinfo("提示", "请输入新密码!")
self.__text33.focus()
elif self.__result[0] == TRUE:
self.__SaveChange(self.__user, self.__CipherText)
else:
tkinter.messagebox.showinfo("提示", "账号密码错误!")
self.__Clear4()
self.__text32.focus()
# 保存修改后的账号密码信息
def __SaveChange(self, user, CipherText):
try:
self.__cur = self.__conn.cursor()
self.__sql2 = 'update 登录注册表 set password=%s where username=%s'
self.__cur.execute(self.__sql2, (self.__CipherText, self.__user,)) # 将游标对象cur关联sql2语句,保存修改后的账号密码(以密文的形式保存)
self.__conn.commit() # 提交sql2语句到SQL数据库,并执行该语句,查询语句不需要使用commit()
tkinter.messagebox.showinfo("提示", "账号密码修改成功!!")
self.__Clear4()
self.__Form(1) # 跳转主界面self.__Form1,重新登录
except EXCEPTION as ex:
tkinter.messagebox.showinfo("提示", "账号密码修改失败!")
tkinter.messagebox.showinfo("提示", ex)
self.__text32.focus()
# 界面self.__Form5:账号注销
def __Cancel(self):
self.__cur = self.__conn.cursor()
self.__user = self.__label22["text"] # 这里的账号是登录成功后,主界面窗体self.__Form2显示的账号
self.__pwd = self.__text41.get().strip()
self.__CipherText3 = self.__Encrypt(self.__user + self.__pwd) # 对账号和密码进行加盐加密后的密文
self.__sql = 'select password from 登录注册表 where username=%s '
self.__cur.execute(self.__sql, (self.__user,)) # 将游标对象cur关联sql语句,通过user+密文来判断账号密码是否输入正确
self.__result3 = self.__cur.fetchone() # 获取返回值(返回一条记录)
if self.__text41.get().strip() == "":
tkinter.messagebox.showinfo("提示", "密码不得为空!")
self.__text41.focus()
elif self.__result3[0] == self.__CipherText3:
self.__DeleteCancel(self.__user)
else:
tkinter.messagebox.showinfo("提示", "账号密码错误!")
self.__Clear5()
self.__text41.focus()
# 从QL数据库删除注销后的账号信息
def __DeleteCancel(self, user):
try:
self.__cur = self.__conn.cursor()
self.__sql2 = 'delete from 登录注册表 where username=%s '
self.__cur.execute(self.__sql2, (user,)) # 将游标对象cur关联sql2语句,从SQL数据库中删除注销后的账号信息
self.__conn.commit() # 提交sql2语句到SQL数据库,并执行该语句,查询语句不需要使用commit()
tkinter.messagebox.showinfo("提示", "账号注销成功!")
self.__Clear5()
self.__Form(1) # 跳转登录界面self.__Form1
except EXCEPTION as ex:
tkinter.messagebox.showinfo("提示", "账号注销失败!")
tkinter.messagebox.showinfo("提示", ex)
self.__Clear5()
def Main(self):
self.__Form1 = tkinter.Tk() # 创建一个窗体Form1
self.__Form2 = tkinter.Tk() # 创建一个窗体Form2
self.__Form3 = tkinter.Tk() # 创建一个窗体Form3
self.__Form4 = tkinter.Tk() # 创建一个窗体Form4
self.__Form5 = tkinter.Tk() # 创建一个窗体Form5
self.__Form1.title('登录界面')
self.__Form2.title("主界面")
self.__Form3.title("注册界面")
self.__Form4.title("修改密码")
self.__Form5.title("账号注销")
self.__Center(self.__Form1) # 窗体Form1居中显示
self.__Center(self.__Form2) # 窗体Form2居中显示
self.__Center(self.__Form3) # 窗体Form3居中显示
self.__Center(self.__Form4) # 窗体Form4居中显示
self.__Center(self.__Form5) # 窗体Form5居中显示
# 一次性创建5个窗体后,需要用withdraw()来隐藏其他窗口,只显示一个登录窗口Form1
self.__Form2.withdraw() # 隐藏窗体Form2
self.__Form3.withdraw() # 隐藏窗体Form3
self.__Form4.withdraw() # 隐藏窗体Form4
self.__Form5.withdraw() # 隐藏窗体Form5
# 登录界面Form1代码控件
self.__label1 = tkinter.Label(self.__Form1, text="账号", bg="#CFCFCF", font=('微软雅黑', 18), bd=5, relief='flat', justify="center", )
self.__label1.place(x=self.__width / 13, y=self.__height / 16)
self.__label2 = tkinter.Label(self.__Form1, text="密码", bg="#CFCFCF", font=('微软雅黑', 18), bd=5, relief='flat', justify="center")
self.__label2.place(x=self.__width / 13, y=self.__height / 7.4)
self.__text1 = tkinter.Entry(self.__Form1, font=("微软雅黑", 17), relief="flat", width=int(self.__width / 90), borderwidth=5, justify="center")
self.__text1.place(x=self.__width / 7.5, y=self.__height / 16)
self.__text2 = tkinter.Entry(self.__Form1, font=("微软雅黑", 17), show="*", relief="flat", width=int(self.__width / 90), borderwidth=5, justify="center")
self.__text2.place(x=self.__width / 7.5, y=self.__height / 7.4)
self.__text1.focus() # 鼠标光标定位在文本输入框text1上面
self.__button1 = tkinter.Button(self.__Form1, text="登录", bg="#CFCFCF", activebackground="#ffffff", relief='solid', font=('黑体', 17), padx=15, pady=5, command=self.__Login, )
self.__button1.place(x=self.__width / 7.5, y=self.__height / 4.3)
self.__button2 = tkinter.Button(self.__Form1, text="重置", bg="#CFCFCF", activebackground="#ffffff", relief='solid', font=('黑体', 17), padx=15, pady=5, command=self.__Clear1, )
self.__button2.place(x=self.__width / 3.5, y=self.__height / 4.3)
self.__button3 = tkinter.Button(self.__Form1, text="注册", bg="#CFCFCF", activebackground="#ffffff", relief='solid', font=('黑体', 17), padx=15, pady=5, command=lambda: self.__Form(3), )
self.__button3.place(x=self.__width / 7.5, y=self.__height / 3)
self.__button4 = tkinter.Button(self.__Form1, text="退出", bg="#CFCFCF", activebackground="#ffffff", relief='solid', font=('黑体', 17), padx=15, pady=5, command=self.__Exit)
self.__button4.place(x=self.__width / 3.5, y=self.__height / 3)
# 注册界面Form3代码控件
self.__label11 = tkinter.Label(self.__Form3, text="注册账号", bg="#CFCFCF", font=('微软雅黑', 18), bd=5, relief='flat', justify="center")
self.__label11.place(x=self.__width / 18, y=self.__height / 16)
self.__label12 = tkinter.Label(self.__Form3, text="输入密码", bg="#CFCFCF", font=('微软雅黑', 18), bd=5, relief='flat', justify="center")
self.__label12.place(x=self.__width / 18, y=self.__height / 8)
self.__label13 = tkinter.Label(self.__Form3, text="确认密码", bg="#CFCFCF", font=('微软雅黑', 18), bd=5, relief='flat', justify="center")
self.__label13.place(x=self.__width / 18, y=self.__height / 5.3)
self.__text11 = tkinter.Entry(self.__Form3, font=("微软雅黑", 17), relief="flat", borderwidth=5, width=int(self.__width / 90), justify="center")
self.__text11.place(x=self.__width / 6.7, y=self.__height / 15.5)
self.__text12 = tkinter.Entry(self.__Form3, font=("微软雅黑", 17), relief="flat", show="*", borderwidth=5, width=int(self.__width / 90), justify="center")
self.__text12.place(x=self.__width / 6.7, y=self.__height / 7.7)
self.__text13 = tkinter.Entry(self.__Form3, font=("微软雅黑", 17), relief="flat", show='*', borderwidth=5, width=int(self.__width / 90), justify="center")
self.__text13.place(x=self.__width / 6.7, y=self.__height / 5.2)
self.__button11 = tkinter.Button(self.__Form3, text="确定", bg="#CFCFCF", activebackground="#ffffff", relief='solid', font=('黑体', 17), padx=15, pady=5, command=self.__Register)
self.__button11.place(x=self.__width / 10, y=self.__height / 3.5)
self.__button12 = tkinter.Button(self.__Form3, text="重置", bg="#CFCFCF", activebackground="#ffffff", relief='solid', font=('黑体', 17), padx=15, pady=5, command=self.__Clear3)
self.__button12.place(x=self.__width / 4.6, y=self.__height / 3.5)
self.__button13 = tkinter.Button(self.__Form3, text="取消", bg="#CFCFCF", activebackground="#ffffff", relief='solid', font=('黑体', 17), padx=15, pady=5, command=lambda: self.__Form(1))
self.__button13.place(x=self.__width / 3, y=self.__height / 3.5)
# 主界面Form2代码控件
self.__button21 = tkinter.Button(self.__Form2, text="退出", bg="#CFCFCF", activebackground="#ffffff", relief='solid', font=('黑体', 17), padx=15, pady=5, command=self.__Exit)
self.__button21.place(x=self.__width / 3.5, y=self.__height / 2.7)
self.__button22 = tkinter.Button(self.__Form2, text="修改密码", bg="#CFCFCF", activebackground="#ffffff", relief='solid', font=("黑体", 17), padx=15, pady=5, command=lambda: self.__Form(4))
self.__button22.place(x=self.__width / 10, y=self.__height / 3.8)
self.__button23 = tkinter.Button(self.__Form2, text="账号注销", bg="#CFCFCF", activebackground="#ffffff", relief='solid', font=("黑体", 17), padx=15, pady=5, command=lambda: self.__Form(5), )
self.__button23.place(x=self.__width / 3.7, y=self.__height / 3.8)
self.__button24 = tkinter.Button(self.__Form2, text="返回", bg="#CFCFCF", activebackground="#ffffff", relief='solid', font=("黑体", 17), padx=15, pady=5, command=self.__reForm1, )
self.__button24.place(x=self.__width / 8.8, y=self.__height / 2.7)
self.__label21 = tkinter.Label(self.__Form2, text="账号:", font=("微软雅黑", 18), padx=10, pady=10, bg="#CFCFCF", relief="flat", justify="center", )
self.__label21.place(x=self.__width / 22, y=self.__height / 18)
self.__label22 = tkinter.Label(self.__Form2, text=self.__text1.get(), font=("微软雅黑", 18), padx=10, pady=10, bg="#CFCFCF", relief="flat", justify="left", )
self.__label22.place(x=self.__width / 10, y=self.__height / 18)
# 修改密码界面Form4代码控件
self.__label32 = tkinter.Label(self.__Form4, text="旧密码", bg="#CFCFCF", font=('微软雅黑', 18), bd=5, relief='flat', justify="center")
self.__label32.place(x=self.__width / 16, y=self.__height / 12)
self.__label33 = tkinter.Label(self.__Form4, text="新密码", bg="#CFCFCF", font=('微软雅黑', 18), bd=5, relief='flat', justify="center")
self.__label33.place(x=self.__width / 16, y=self.__height / 7)
self.__text32 = tkinter.Entry(self.__Form4, font=("微软雅黑", 17), relief="flat", borderwidth=5, width=int(self.__width / 90), justify="center")
self.__text32.place(x=self.__width / 7, y=self.__height / 11.5)
self.__text33 = tkinter.Entry(self.__Form4, font=("微软雅黑", 17), show='*', relief="flat", borderwidth=5, width=int(self.__width / 90), justify="center")
self.__text33.place(x=self.__width / 7, y=self.__height / 6.8)
self.__button31 = tkinter.Button(self.__Form4, text="确定", bg="#CFCFCF", activebackground="#ffffff", relief='solid', font=('黑体', 17), padx=15, pady=5, command=self.__Change)
self.__button31.place(x=self.__width / 9.5, y=self.__height / 3.8)
self.__button32 = tkinter.Button(self.__Form4, text="重置", bg="#CFCFCF", activebackground="#ffffff", relief='solid', font=('黑体', 17), padx=15, pady=5, command=self.__Clear4)
self.__button32.place(x=self.__width / 4.5, y=self.__height / 3.8)
self.__button33 = tkinter.Button(self.__Form4, text="取消", bg="#CFCFCF", activebackground="#ffffff", relief='solid', font=('黑体', 17), padx=15, pady=5, command=lambda: self.__Form(2))
self.__button33.place(x=self.__width / 3, y=self.__height / 3.8)
# 账号注销界面Form5代码控件
self.__label41 = tkinter.Label(self.__Form5, text="账号密码", bg="#CFCFCF", font=('微软雅黑', 18), bd=5, relief='flat', justify="center")
self.__label41.place(x=self.__width / 18, y=self.__height / 10)
self.__text41 = tkinter.Entry(self.__Form5, font=("微软雅黑", 17), relief="flat", borderwidth=5, width=int(self.__width / 95), justify="center")
self.__text41.place(x=self.__width / 6.8, y=self.__height / 9.6)
self.__button41 = tkinter.Button(self.__Form5, text="注销", bg="#CFCFCF", activebackground="#ffffff", relief='solid', font=('黑体', 17), padx=15, pady=5, command=self.__Cancel, )
self.__button41.place(x=self.__width / 10, y=self.__height / 4.5)
self.__button42 = tkinter.Button(self.__Form5, text="重置", bg="#CFCFCF", activebackground="#ffffff", relief='solid', font=('黑体', 17), padx=15, pady=5, command=self.__Clear5, )
self.__button42.place(x=self.__width / 4.7, y=self.__height / 4.5)
self.__button43 = tkinter.Button(self.__Form5, text="取消", bg="#CFCFCF", activebackground="#ffffff", relief='solid', font=('黑体', 17), padx=15, pady=5, command=lambda: self.__Form(2), )
self.__button43.place(x=self.__width / 3, y=self.__height / 4.5)
self.__Form5.mainloop()
self.__Form4.mainloop()
self.__Form3.mainloop()
self.__Form2.mainloop()
self.__Form1.mainloop()
if __name__ == '__main__':
st = Account()
st.Main()
以上就是这个登录程序的全部源代码以及相关说明,仅供学习和参考,感兴趣的小伙伴可以来看看。因为是第一次写的代码程序,还有一些不足之处,有些冗长的部分可以简化,虽然代码比较长,但是原理步骤都差不多,也欢迎大家批评指正。这里我还做了一个不需要连接数据库的窗体登录程序:Python Tkinter窗体程序通过列表和字典来实现账号登录、注册、修改、注销等功能。
最后
以上就是满意草莓为你收集整理的Python Tkinter窗体程序连接SQL Server数据库实现账号登录、注册、修改、注销等功能(不定时更新)的全部内容,希望文章能够帮你解决Python Tkinter窗体程序连接SQL Server数据库实现账号登录、注册、修改、注销等功能(不定时更新)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复