python-mysql期末实验:三、程序登录、注册界面的制作

本专栏目录:

一、实验综述

二、基于MySQL进行的数据库的搭建

三、程序登录、注册界面的制作(即本篇)

四、数据导入界面的制作

五、collage(大学)表的增删改查界面的制作

六、province(省份)表的增删改查界面的制作

七、student_num(考生人数)表的增删改查界面以及数据可视化的制作

八、min_score_line(最低分数线)表的增删改查界面以及数据可视化的制作

九、collage_level(学校等级)表的增删改查界面的制作

十、enrollment_type(招生类型)表的增删改查界面的制作

十一、enrollment(招生人数)表的增删改查界面以及数据可视化的制作

十二、school_type(学校类型)表的增删改查界面的制作

十三、collage_school_level(各高校等级)表的增删改查界面的制作

十四、collage_province_enrollment_type(各高校招生类型)表的增删改查界面的制作

如果需要整个代码文件,以及数据库中的数据,或者有较为复杂的问题,请添加QQ:3095631599(CSDN-山河之书),添加时请备注:CSDN。

本部分将正式进入程序的编写,将叙述如何基于数据库中的user(用户)表搭建出一个看上去还算可以的登录以及注册界面;

这部分总共包括四个界面:初始界面,注册界面,使用指南界面以及登陆成功后的功能、表格选择界面;

可以实现的功能包括:支持账号密码验证登录,支持未注册账号提醒注册,支持密码输入格式规范化检查,支持密码防误差二次验证,支持用户名重复性检查,支持邮箱格式规范化检查,支持账号密码空值检查,支持成绩输入非整数检查,支持对除账户表格外其他表格进行选择,并进入增删改查界面或数据导入表格选择界面。

接下来将舞台交给代码段,所有的解释都将以注释的形式呈现:

import tkinter as tk  # 本代码段需用
import pymysql as py  # 本代码段需用
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from tkinter import ttk
from tkinter import messagebox  # 本代码段需用
import re  # 本代码段需用
import turtle  # 本代码段需用
import random  # 本代码段需用
import time  # 本代码段需用


# 配置数据库IP,只有明确了IP,才能连接数据库,这个IP的意思实际上是本机IP,由于一些技术上的原因,导致该程序无法跨局域网运行,因此直接开摆,干脆只让它在主机运行
ip = "127.0.0.1"


# 窗口
window = tk.Tk()  # 这是主窗口,也就是所说的初始界面
window.title("欢迎使用本系统")  # 窗口名
window.geometry("450x300")  # 窗口大小


# 背景图片
canvas = tk.Canvas(window, height=1450, width=1300)  # 背景画布大小以及画布的所在窗口,即主窗口
image0 = tk.PhotoImage(file="樱顶1.png")  # 设定背景图像路径,这张图片是什么随便你
image = canvas.create_image(0, 0, anchor="nw", image=image0)  # 设置图像位置等参数
canvas.pack(side="top")


# 标签
tk.Label(window, text="高校报考信息查询系统").place(x=170, y=60)  # 设置提示文本及像素位置
tk.Label(window, text="请切记务必在使用本系统前仔细阅读使用说明,不然保证无法使用").place(x=60, y=90)
tk.Label(window, text="用户名:").place(x=100, y=150)  # 这是用户名输入框的提示文字
tk.Label(window, text="密码:").place(x=100, y=190)  # 类上


# 输入框
username_input = tk.StringVar()
frame_username_input = tk.Entry(window, textvariable=username_input)
frame_username_input.place(x=160, y=150)  # 设置账号输入框及其位置,并获取输入值
password_input = tk.StringVar()
frame_password_input = tk.Entry(window, textvariable=password_input, show="*")  # 密码输入全部用*隐藏
frame_password_input.place(x=160, y=190)  # 设置账号输入框及其位置,并获取输入值


# 登录函数
def log_in():
    username = username_input.get()
    password = password_input.get()  # 获取账号密码的输入值
    conn = py.connect(host='%s' % ip, user='lzx', password='lzx', port=3306, database='dbms_report',
                      charset='utf8')  # 登录数据库,建立数据库连接,账号密码端口啥的都是自己在数据库那边设好的,不是固定的
    cursor = conn.cursor()  # 设置游标
    a = cursor.execute("select * from user")  # 执行SQL语句
    b = cursor.fetchall()  # 获取SQL执行结果
    list_usernames = []
    list_passwords = []  # 预设两个空的列表
    for i in range(0, a):
        list_usernames.append(b[i][0])
        list_passwords.append(b[i][1])  # 获取数据一一对应输入新列表(列表有序性的好处就体现出来了)
    dict_users = dict(zip(list_usernames, list_passwords))  # 拼接列表形成字典,用于密码校验(即账号密码一一对应)
    if username in list_usernames:  # 检查账号是否存在
        if password == dict_users[username]:  # 账号存在的话,检查密码是否正确
            tk.messagebox.showinfo(title="welcome", message=username+",欢迎您")  # 密码校验成功进入主系统,并弹出欢迎窗口
            choose()  # 运行功能、表格选择界面函数
        else:
            tk.messagebox.showerror(message="密码错误")  # 密码校验失败弹出警示窗口
    elif username == "":
        tk.messagebox.showerror(message="用户名不能为空")  # 检查用户名不能为空,弹出警示窗口
    elif password == "":
        tk.messagebox.showerror(message="密码不能为空")  # 检查密码不能为空,弹出警示窗口
    else:
        sign_up_ask = tk.messagebox.askyesno("提醒", "您尚未注册,是否注册?")  # 提示注册并选择是与否
        if sign_up_ask is True:
            sign_up()  # 是,运行注册界面函数
    conn.commit()  # 事务成功运行完成
    conn.close()  # 关闭连接


# 注册界面函数
def sign_up():
    # 写入函数
    def save_user():
        try:
            conn = py.connect(host='%s' % ip, user='lzx', password='lzx', port=3306, database='dbms_report',
                              charset='utf8')
            cursor = conn.cursor()
            # 密码等检查
            try:
                save_username = str(new_username.get())
                save_password = str(new_password.get())
                save_password_confirm = str(new_password_confirm.get())
                save_user_e_mail = str(user_e_mail.get())
                save_province_name = str(province_name.get())
                save_score = int(score.get())  # 获取数据,为数字检查做准备,至于这个数据哪里来的,还请往后看,输入框啥的在后面,不能放在前面的原因在于运行顺序的问题。
                pattern_password = r"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[0-9a-zA-Z]{8,12}$"  # 正则表达式:密码8到12位,且需要包含数字以及大小写字母
                pattern_e_mail = r"^[0-9a-zA-Z]+(@)[0-9a-zA-Z]+\.(com)$"  # 正则表达式校验邮箱格式:xxx@xxx.com
                result_password = re.match(pattern_password, save_password)  # 校验密码格式
                result_e_mail = re.match(pattern_e_mail, save_user_e_mail)  # 校验邮箱格式
                if save_username == "" or save_password == "":
                    tk.messagebox.showerror("错误", "用户名或密码不能为空")
                elif not result_password:
                    tk.messagebox.showerror("错误", "请输入8到12位由数字、大小写字母构成的密码")
                elif not result_e_mail:
                    tk.messagebox.showerror("错误", "请输入正确的电子邮箱")
                elif save_password_confirm != save_password:  # 密码两次输入结果一致性校验
                    tk.messagebox.showerror("错误", "密码前后不一致")  # 上面这一堆不合规范的解释想必都看得懂,对于result_password以及result_e_mail,当校验成功时会返回True,反之则为False
                else:
                    sql = "insert into user(user_name,user_password,user_e_mail,province_name,score)\
                        values('%s','%s','%s','%s',%d)"\
                        % (save_username, save_password, save_user_e_mail, save_province_name, save_score)  # 校验完成,将信息写入数据库,%的用途大家应该看得懂
                    cursor.execute(sql)  #执行上面的SQL语句
                    cursor.execute("select * from user")  # 查询全部用户
                    list_sql2 = cursor.fetchall()  # 获取全部用户
                    row_sql2 = len(list_sql2)  # 统计的已注册用户列表的长度,从而获得已注册用户的数量
                    conn.commit()
                    conn.close()
                    tk.messagebox.showinfo("欢迎", "您是第%d位用户" % row_sql2)  # 美好的提示,虽然没有实际用途
                    window_sign_up.destroy()  # 关闭窗口
            except py.err.IntegrityError:
                tk.messagebox.showerror("错误", "用户名已存在或省份输入格式不正确")  # 利用数据库主码特性(实体完整性原则)进行检查
        except ValueError:
            tk.messagebox.showerror("错误", "成绩应为数字")  # 前面设置了int,防止输入一些乱七八糟的值
    # 注册界面,以下的这些和前面初始界面搭建的结构是完全一样的逻辑
    window_sign_up = tk.Toplevel(window)
    window_sign_up.geometry("350x320")
    window_sign_up.title("注册")
    # 新建用户名
    new_username = tk.StringVar()
    tk.Label(window_sign_up, text="请输入用户名:").place(x=10, y=10)
    tk.Entry(window_sign_up, textvariable=new_username).place(x=150, y=10)
    # 新建密码
    new_password = tk.StringVar()
    tk.Label(window_sign_up, text="请输入8-12位包含\n大小写字母和数字的密码:").place(x=10, y=40)
    tk.Entry(window_sign_up, textvariable=new_password, show="*").place(x=150, y=50)
    # 再次输入密码
    new_password_confirm = tk.StringVar()
    tk.Label(window_sign_up, text="请再次输入密码:").place(x=10, y=90)
    tk.Entry(window_sign_up, textvariable=new_password_confirm, show="*").place(x=150, y=90)
    # 输入邮箱
    user_e_mail = tk.StringVar()
    tk.Label(window_sign_up, text="请输入邮箱:").place(x=10, y=130)
    tk.Entry(window_sign_up, textvariable=user_e_mail).place(x=150, y=130)
    # 输入省份
    province_name = tk.StringVar()
    tk.Label(window_sign_up, text="请输入省份:").place(x=10, y=170)
    tk.Entry(window_sign_up, textvariable=province_name).place(x=150, y=170)
    # 输入分数
    score = tk.StringVar()
    tk.Label(window_sign_up, text="请输入分数:").place(x=10, y=210)
    tk.Entry(window_sign_up, textvariable=score).place(x=150, y=210)
    # 确认注册按钮
    confirm_sign_up = tk.Button(window_sign_up, text="注册", command=save_user)
    confirm_sign_up.place(x=150, y=250)


# 退出的函数
def quit_windows():
    window.destroy()  # 关闭窗口
    main()  # 启动彩蛋函数


# 彩蛋函数三连(tree,petal,main),这段代码网上抄的,没啥意义,就是图一乐
def trees(branch_len, t):
    time.sleep(0.000005)
    if branch_len > 3:
        if 8 <= branch_len <= 12:
            if random.randint(0, 2) == 0:
                t.color('snow')
            else:
                t.color('light coral')
            t.pensize(branch_len / 3)
        elif branch_len < 8:
            if random.randint(0, 1) == 0:
                t.color('snow')
            else:
                t.color('light coral')
            t.pensize(branch_len / 2)
        else:
            t.color('sienna')
            t.pensize(branch_len / 10)
        t.forward(branch_len)
        a = 1.5 * random.random()
        t.right(20 * a)
        b = 1.5 * random.random()
        trees(branch_len - 10 * b, t)
        t.left(40 * a)
        trees(branch_len - 10 * b, t)
        t.right(20 * a)
        t.speed(100)
        t.up()
        t.backward(branch_len)
        t.down()


def petal(m, t):
    for i in range(m):
        a = 200 - 400 * random.random()
        b = 10 - 20 * random.random()
        t.speed(100)
        t.up()
        t.forward(b)
        t.left(90)
        t.forward(a)
        t.down()
        t.color('light coral')
        t.circle(1)
        t.up()
        t.backward(a)
        t.right(90)
        t.backward(b)


def main():
    t = turtle.Turtle()
    w = turtle.Screen()
    t.hideturtle()
    t.getscreen().tracer(5, 0)
    w.screensize(canvwidth=1000, canvheight=1000, bg="wheat")
    t.speed(100)
    t.left(90)
    t.up()
    t.backward(150)
    t.down()
    t.color('sienna')
    trees(60, t)
    petal(200, t)
    w.exitonclick()


# 使用手册界面函数
def for_users():
    window_user_page = tk.Tk()
    window_user_page.geometry("450x330")
    window_user_page.title("使用指南")
    tk.Label(window_user_page, text="1.使用前请现将随程序附带的数据库dbms_report安装至MySQL中并保持原名").place(x=0, y=0)
    tk.Label(window_user_page, text="2.该系统默认的MySQL连接信息为IP:127.0.0.1,账户密码均为lzx,字符集为utf8").\
        place(x=0, y=30)
    tk.Label(window_user_page, text="2.本系统配置了查询、插入和修改数据三个主要功能,但未设置级联操作").place(x=0, y=60)
    tk.Label(window_user_page, text="3.插入和删除均受到外键限制,为保护数据库,每次删除仅能删除一条至数条数据").place(x=0, y=90)
    tk.Label(window_user_page, text="4.本系统基于DBMS MySQL搭建,使用MySQL自带的并发控制机制").place(x=0, y=120)
    tk.Label(window_user_page, text="5.标注有“关键词”字样的输入框是查询所需的关键词,如果不予限制将输出整表").place(x=0, y=150)
    tk.Label(window_user_page, text="6.本表支持模糊关键字查询,例如,输入“山”会返回山东省和山西省的数据").place(x=0, y=180)
    tk.Label(window_user_page, text="7.当点击查询却无返回结果时,请检查您的关键词使用是否正确").place(x=0, y=210)
    tk.Label(window_user_page, text="8.所有表格均支持不完全关键字查询").place(x=0, y=240)
    tk.Label(window_user_page, text="9.图像显示可能不清晰,尤其是坐标轴,受制于matplotlib本身限制,暂时无法解决").place(x=0, y=270)
    tk.Label(window_user_page, text="10.请勿删库,已备份,删库无用,删库封号").place(x=0, y=300)


# 主界面登录、注册、退出、使用指南按钮
login = tk.Button(window, text="登录", command=log_in)  # command后面的函数就是点击这个键的时候要运行的函数
login.place(x=140, y=230)
logup = tk.Button(window, text="注册", command=sign_up)
logup.place(x=210, y=230)
logdown = tk.Button(window, text="退出", command=quit_windows)
logdown.place(x=280, y=230)
user_page = tk.Button(window, text="使用指南", command=for_users)
user_page.place(x=199, y=270)


# 功能、表格选择函数,还是和前面完全一样的逻辑,看懂前面的一样的逻辑,创建一个界面,在上面堆一堆按钮和提示文字之类的,这上面的command都对应了一个界面函数,前十个在以后会单独讲,最后一个就是下一部分要讲的数据导入界面
def choose():
    window_choose = tk.Tk()
    window_choose.title("表格选择")
    window_choose.geometry("450x300")
    tk.Label(window_choose, text="高校报考信息查询系统").place(x=160, y=0)
    tk.Label(window_choose, text="请选择表格").place(x=190, y=20)
    collage = tk.Button(window_choose, text="大学", command=collage_use)
    collage.place(x=0, y=50)
    province = tk.Button(window_choose, text="省份", command=province_use)
    province.place(x=0, y=80)
    student_num = tk.Button(window_choose, text="考生人数", command=student_num_use)
    student_num.place(x=0, y=110)
    min_score_line = tk.Button(window_choose, text="最低分数线", command=min_score_line_use)
    min_score_line.place(x=0, y=140)
    school_level = tk.Button(window_choose, text="学校等级", command=school_level_use)
    school_level.place(x=0, y=170)
    enrollment_type = tk.Button(window_choose, text="招生类型", command=enrollment_type_use)
    enrollment_type.place(x=225, y=50)
    enrollment = tk.Button(window_choose, text="招生人数", command=enrollment_use)
    enrollment.place(x=225, y=80)
    school_type = tk.Button(window_choose, text="学校类型", command=school_type_use)
    school_type.place(x=225, y=110)
    collage_school_level = tk.Button(window_choose, text="各高校等级", command=collage_school_level_use)
    collage_school_level.place(x=225, y=140)
    collage_province_enrollment_type = tk.Button(window_choose, text="各高校招生类型",
                                                 command=collage_province_enrollment_type_use)
    collage_province_enrollment_type.place(x=225, y=170)
    load_data = tk.Button(window_choose, text="导入数据", command=load_data_choose)
    load_data.place(x=125, y=230)  # 运行数据导入程序

    # 返回函数,就是关闭窗口
    def quit_window_choose():
        window_choose.destroy()
    quit_window_choose = tk.Button(window_choose, text="返回", command=quit_window_choose)  # 返回键
    quit_window_choose.place(x=280, y=230)

喜闻乐见的运行截图:

 

 

 

 

 

 

 

 

 

 

 

 

  • 4
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山河之书Liu_Zixin

不要打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值