若重启2020,tkinter陪你详细打造一个python简易GUI界面完成学生选课系统!

如果你的2020年重启,你最想干什么?我想狠狠的扇自己一巴掌,为什么大一不好好读书,搞到现在大二多了才意识到读书的重要性,我第一件事就想把我大一的实训任务好好的认真做一做,所以我最近一段时间,我都在看tkinter文档,终于搞好了,那我说说我是怎么做的吧!

效果图

在这里插入图片描述
毕竟我这个做的是一个实训项目,代码可能会有一点多,但是绝对很详细,希望看的朋友耐心点,绝对能学到点东西。

库的选择

对于GUI库网上一般有三种:wxpython,pyqt5 还有tkinter自带库,我对库的选择没多大要求,就从那个能简单上手来说,我就选择的是tkinter库,如果对这个很感兴趣,我推荐后面可以学习wxpython。

库的学习

对于tkinter库来说,官方文档确实烂的不行,很多也不完整,但是我也找到了一个博主的教学博客:tkinter笔记 相对来说,我觉得写的挺不错的。

库的效果和各部分代码

主界面:

在这里插入图片描述
解析: 我加一个时间控件,然后设计了一个登入系统,就是run函数里面,账号密码的都可以自己改的,登入成功的话,就会把用户名追加到下面颜色框里面,登入失败的话,也会有对应的提示。
代码:


def get_time():  # 屏幕刷新时间
    time_str = time.strftime("%H:%M:%S", time.localtime())  # 获得系统现在时间
    label_4.configure(text=time_str)  # 重新设置文本标签
    my_windows.after(1000, get_time)


def run(x):  # 确定账号
    a = x
    if inp1.get() == "沙漏在下雨" and inp2.get() == "123123":  # 判断用户是否正确
        s = "尊敬的客户:{}你已经登入成功进入该系统!\n".format(a)
        txt.insert(END, s)  # 追加显示运算结果
        inp1.delete(0, END)  # 清空输入
        inp2.delete(0, END)  # 清空输入
        new_windows(my_windows)  # 进去新界面
    else:
        s = "信息输入错误!请重新输入!\n"
        txt.insert(END, s)  # 追加显示运算结果
        inp1.delete(0, END)  # 清空输入
        inp2.delete(0, END)  # 清空输入


def bi_gon1():  # 彩蛋
    s = '加油加油每一天'
    bi_gon.config(text=s)


my_windows = Tk()  # 初始化TK()
my_windows.title("学生选课系统")  # 设置标题
width = 500
height = 400
# 获取屏幕尺寸以计算布局参数,让窗口位于屏幕中央
screenwidth = my_windows.winfo_screenwidth()
screenheight = my_windows.winfo_screenheight()
align_str = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)

my_windows.geometry(align_str)  # 设置窗口大小

my_windows.resizable(width=True, height=True)
# 设置窗口是否可变长、宽,True:可变,False:不可变

label_0 = Label(my_windows, text="学生选修课程系统设计", bg="#00BFFF", fg="red", font=("宋体", 30), relief=GROOVE)
label_0.pack()
label_1 = Label(my_windows, text="---------请开始选择课程之旅!---------", font=("宋体", 20)).pack()
# 二个标题之上
inp1 = Entry(my_windows)  # 定义第一个输入框
inp1.place(relx=0.35, rely=0.2, relwidth=0.3, relheight=0.1)
inp2 = Entry(my_windows, show="*", )  # 定义第二个输入框  且密码隐藏
inp2.place(relx=0.35, rely=0.3, relwidth=0.3, relheight=0.1)

inp_label1 = Label(my_windows, text="账号:", font=("宋体", 20))  # 定义账号
inp_label1.place(relx=0.20, rely=0.20)
inp_label2 = Label(my_windows, text="密码:", font=("宋体", 20))  # 定义密码
inp_label2.place(relx=0.20, rely=0.30)

btn1 = Button(my_windows, text='登入系统', command=lambda: run(inp1.get()))  # 登入系统的按钮
btn1.place(relx=0.35, rely=0.4, relwidth=0.3, relheight=0.1)
label_3 = Label(my_windows, text="原创作品谢谢支持!学习交流QQ:884427640", font=("宋体", 10))
label_3.place(relx=0.26, rely=0.5)
label_4 = Label(my_windows, text=" ", fg="blue", font=("黑体", 20))
label_4.place(relx=0.37, rely=0.55)
get_time()
#  定义一个娱乐彩蛋
bi_gon = Button(my_windows, text="点我点我,有惊喜!", font=("宋体", 10), command=bi_gon1)
bi_gon.place(relx=0.65, rely=0.56)

txt = Text(my_windows, bg="#d3fbfb")  # 定义文本框
txt.place(rely=0.65, relheight=0.4)
my_windows.mainloop()

功能项:

在这里插入图片描述
解析:这里用到的是tk的单选框控件,其实就是在主界面的确定按钮里面加入的函数中创建了一个子窗口,控制住界面的大小和布局的参数在主界面已经给了,因为是全局变量,所以后面我直接引用的。
代码:

def new_windows(windows):  # 登入界面成功后的窗口
    winNew = Toplevel()
    winNew.geometry(align_str)  # 设置窗口大小保持和主窗口相同
    winNew.resizable(width=True, height=True)
    # 设置窗口是否可变长、宽,True:可变,False:不可变
    winNew.title('系统菜单模式')
    label_a = Label(winNew, text="学生选修课程系统设计", bg="#00BFFF", fg="red", font=("宋体", 30), relief=GROOVE).pack()
    label_b = Label(winNew, text="---------请开始选择课程之旅!---------", font=("宋体", 20)).pack()
    # 二个一样的标签  下面设置功能模块
    var = IntVar()  # 设置选择属性 下面为单选框各模块
    rd1 = Radiobutton(winNew, text="课程录入", variable=var, value=0, command=lambda: menu(var.get()))
    rd1.place(relx=0.4, rely=0.3)  # 标签课程录入

    rd2 = Radiobutton(winNew, text="课程浏览", variable=var, value=1, command=lambda: menu(var.get()))
    rd2.place(relx=0.4, rely=0.4)  # 标签课程浏览

    rd3 = Radiobutton(winNew, text="课程选择", variable=var, value=2, command=lambda: menu(var.get()))
    rd3.place(relx=0.4, rely=0.5)  # 标签课程选择

    rd4 = Radiobutton(winNew, text="课程查询", variable=var, value=3, command=lambda: menu(var.get()))
    rd4.place(relx=0.4, rely=0.6)  # 标签课程查询
    btClose = Button(winNew, text='关闭程序', command=winNew.destroy)
    btClose.place(relx=0.7, rely=0.7)

录入课程:

在这里插入图片描述
解析:同样,也是新建了一个子窗口,然后加入各种标签和按钮,然后对应的各个函数完成相应的功能,这里点击确定的话,我们会调用到一个子函数模块,用文件的方式去把输入的值保存起来,要用到os库的一点知识,但是不难。
代码:

def luru():  # 录入函数
    print("录入")
    winNew1 = Toplevel()
    winNew1.title("录入课程模式")
    winNew1.geometry(align_str)  # 设置窗口大小 和原窗口一样
    winNew1.resizable(width=True, height=True)
    # 设置窗口是否可变长、宽,True:可变,False:不可变
    label_6 = Label(winNew1, text="学生选修课程系统设计", bg="#00BFFF", fg="red", font=("宋体", 30), relief=GROOVE).pack()
    label_7 = Label(winNew1, text="---------请开始选择课程之旅!---------", font=("宋体", 20)).pack()
    # 设置警告备注
    label_00 = Label(winNew1, text="PS:在校学生课程学分总和不得少于60分!输入课程学分请谨慎!", font=("宋体", 10))
    label_00.place(relx=0, rely=0.2)
    label_8 = Label(winNew1, text="课程编号:", font=("宋体", 10)).place(relx=0, rely=0.3)
    label_9 = Label(winNew1, text="课程名称:", font=("宋体", 10)).place(relx=0.5, rely=0.3)
    label_10 = Label(winNew1, text="课程性质:", font=("宋体", 10)).place(relx=0, rely=0.4)  # 专业 还是 公开
    label_11 = Label(winNew1, text="任课老师:", font=("宋体", 10)).place(relx=0.5, rely=0.4)
    label_12 = Label(winNew1, text="课程学分:", font=("宋体", 10)).place(relx=0, rely=0.5)
    label_13 = Label(winNew1, text="开课时间:", font=("宋体", 10)).place(relx=0.5, rely=0.5)
    inp8 = Entry(winNew1)  # 定义8输入框
    inp8.place(relx=0.15, rely=0.3)
    inp9 = Entry(winNew1)  # 定义9输入框
    inp9.place(relx=0.65, rely=0.3)
    inp10 = Entry(winNew1)  # 定义10输入框
    inp10.place(relx=0.15, rely=0.4)
    inp11 = Entry(winNew1)  # 定义11输入框
    inp11.place(relx=0.65, rely=0.4)
    inp12 = Entry(winNew1)  # 定义12输入框
    inp12.place(relx=0.15, rely=0.5)
    inp13 = Entry(winNew1)  # 定义13入框
    inp13.place(relx=0.65, rely=0.5)
    text1 = Text(winNew1, bg="#d3fbfb")  # 打印文本
    text1.place(rely=0.7)
    btn2 = Button(winNew1, text='确定',
                  command=lambda: lurufile(inp8.get(), inp9.get(), inp10.get(), inp11.get(), inp12.get(), inp13.get(),
                                           text1,
                                           inp8, inp9, inp10, inp11, inp12, inp13))  # 确定按钮
    btn2.place(relx=0.35, rely=0.6)
    btClose2 = Button(winNew1, text='关闭', command=winNew1.destroy)  # 取消按钮
    btClose2.place(relx=0.55, rely=0.6)


这里调用到了lurufile() ,然后在这个函数里面,我们把输入的值全部清空,方便后续输入:

def lurufile(aa, b, c, d, e, f, text1, a8, a9, a10, a11, a12, a13):  # 写入到文件 成功!
    print(b)  # 检验传值是否成功
    if not os.path.exists("D://课程//"):  # 判断目录是否存在
        os.mkdir("D://课程//")  # 建立这个目录
    else:
        s = "课程编号:{}\t课程名称:{}\t课程性质:{}\t任课老师:{}\t课程学分:{}\t开课时间:{}\n".format(aa, b, c, d, e, f)
        ss = "课程:{}已经录入成功!(D://课程//课程信息.txt)\n".format(b)
        if aa:  # 排除空值
            with open("D://课程//课程信息.txt", "a+") as fo:
                fo.write(s)
                text1.insert(END, ss)  # 追加显示运算结果
                a8.delete(0, END)  # 清空输入
                a9.delete(0, END)  # 清空输入
                a10.delete(0, END)  # 清空输入
                a11.delete(0, END)  # 清空输入
                a12.delete(0, END)  # 清空输入
                a13.delete(0, END)  # 清空输入

浏览课程:

在这里插入图片描述
解析:这里面就是读取我们刚才创建好的文件,然后把他写到这个颜色框里面,准确来说是写入text模块中,我这个界面可能长度小了点哈,,,不碍事不碍事。
代码:

def look():  # 浏览函数
    print("浏览")
    winNew2 = Toplevel()
    winNew2.geometry(align_str)  # 设置窗口大小 和原窗口一致
    winNew2.resizable(width=True, height=True)
    # 设置窗口是否可变长、宽,True:可变,False:不可变
    winNew2.title('浏览课程模式')
    label_a = Label(winNew2, text="学生选修课程系统设计", bg="#00BFFF", fg="red", font=("宋体", 30), relief=GROOVE).pack()
    label_b = Label(winNew2, text="---------请开始选择课程之旅!---------", font=("宋体", 20)).pack()
    # 定义上面的窗口界面
    text2 = Text(winNew2, bg="#d3fbfb")
    text2.place(rely=0.3)
    with open("D://课程//课程信息.txt", "r") as kc:  # 打开文件
        for i in kc:  # 遍历这个txt
            text2.insert(END, i + "\n")
    btClose3 = Button(winNew2, text='关闭', command=winNew2.destroy)  # 取消按钮
    btClose3.place(relx=0.7, rely=0.2)

选择课程:

在这里插入图片描述
解析:这里我们用到了判空方法,就是一个防止误操作的手段,很简单的,我在代码里面给出了,这里也是子窗口加标签和按钮,然后输入值,传给一个函数去写入文件,最后成功的话,就在text里面展示出来,或者显示其他信息。
代码:

def choose():  # 选择函数
    print("选择")
    winNew3 = Toplevel()
    winNew3.geometry(align_str)  # 设置窗口大小 和原窗口一样
    winNew3.resizable(width=True, height=True)
    # 设置窗口是否可变长、宽,True:可变,False:不可变
    winNew3.title('选择课程模式')
    label_a = Label(winNew3, text="学生选修课程系统设计", bg="#00BFFF", fg="red", font=("宋体", 30), relief=GROOVE).pack()
    label_b = Label(winNew3, text="---------请开始选择课程之旅!---------", font=("宋体", 20)).pack()
    # 定义上面的窗口界面
    # 我们假定一个人最多就只能选择5~6门课程
    label_15 = Label(winNew3, text="PS:在校学生请选择5至6门课程,且学分总和不得少于60分!", font=("宋体", 10)).place(relx=0, rely=0.2)
    label_16 = Label(winNew3, text="输入学生姓名:", font=("宋体", 10)).place(relx=0.2, rely=0.3)
    label_17 = Label(winNew3, text="输入学生学号:", font=("宋体", 10)).place(relx=0.2, rely=0.4)
    ps = Label(winNew3, text="(规定学号长度为4位)", font=("黑体", 8)).place(relx=0.16, rely=0.46)
    label_18 = Label(winNew3, text="输入课程名称(1-6):", font=("宋体", 10)).place(relx=0.13, rely=0.5)
    # 下面定义所有的输入框
    inp16 = Entry(winNew3)  # 定义16输入框 姓名
    inp16.place(relx=0.38, rely=0.3)
    inp17 = Entry(winNew3)  # 定义17输入框 学号
    inp17.place(relx=0.38, rely=0.4)
    inp181 = Entry(winNew3)  # 定义181输入框 课程1
    inp181.place(relx=0.38, rely=0.5)
    inp182 = Entry(winNew3)  # 定义182输入框 课程2
    inp182.place(relx=0.68, rely=0.5)
    inp183 = Entry(winNew3)  # 定义183输入框 课程3
    inp183.place(relx=0.38, rely=0.55)
    inp184 = Entry(winNew3)  # 定义184输入框 课程3
    inp184.place(relx=0.68, rely=0.55)
    inp185 = Entry(winNew3)  # 定义185输入框 课程5
    inp185.place(relx=0.38, rely=0.6)
    inp186 = Entry(winNew3)  # 定义186输入框 课程6
    inp186.place(relx=0.68, rely=0.6)
    text3 = Text(winNew3, bg="#d3fbfb")
    text3.place(rely=0.73)  # 定义第三个文本框
    # 定义确定和推出按钮
    btn3 = Button(winNew3, text='确定', command=lambda: choosefile(inp16.get(), inp17.get(), inp181.get(),
                                                                 inp182.get(), inp183.get(), inp184.get(), inp185.get(),
                                                                 inp186.get(), text3, inp16, inp17, inp181,
                                                                 inp182, inp183, inp184, inp185, inp186))
    # 确定按钮 然后把所有值 送到choosefile中  同样写入文件
    btn3.place(relx=0.38, rely=0.65)
    btClose3 = Button(winNew3, text='关闭', command=winNew3.destroy)  # 关闭按钮
    btClose3.place(relx=0.68, rely=0.65)

这里也是用到了一个函数chosefile(),里面用了几个判空操作,在代码里面我也有加入注释,这个作用就是把填入的值写入文件里面.
代码:


def choosefile(i16, i17, i181, i182, i183, i184, i185, i186, text3, ip16, ip17, ip181, ip182, ip183, ip184, ip185,
               ip186):
    # 将学生选好的课程 对应他的学号姓名, 一样的写入到文件里面  成功实现
    print(i16)  # 检验传值是否成功
    class_list = []  # 总课程列表
    class_list0 = []  # 暂存
    with open("D://课程//课程信息.txt", "r") as kc:
        for i in kc:
            s = i.strip("\n").split("\t")  # 取文件里面每一行去掉空格 去掉换行 后的列表
            # print(s[1])  #课程名称:大学语文
            class_list0.append(str(s[1]))
        for j in class_list0:
            # print(j[5:9])
            class_list.append(str(j[5:9]))
        print(class_list)  # 课程一共长度为5 这个也是课程总列表

    number_list = []  # 总学号列表
    number_list0 = []  # 暂存区 = =
    with open("D://课程//课程信息.txt", "r") as xh:
        for i in xh:
            s = i.strip("\n").split("\t")  # 取文件里面每一行去掉空格 去掉换行 后的列表
            print(s[1])  # 学生学号:0001
            number_list0.append(str(s[1]))
        for jj in number_list0:
            print(jj[6:10])
            number_list.append(str(jj[6:10]))
    # print(class_list)  # 学号一共长度 这个也是学号总列表
    nl = set(number_list)  # 将学号形成集合   然后进行判断
    print(nl)

    if not os.path.exists("D://课程//"):  # 判断这个目录是否存在
        os.mkdir("D://课程//")  # 建立这个目录
    else:
        s = "学生姓名:{}\t 学生学号:{}\t  课程一:{}\t课程二:{}\t课程三:{}\t课程四:{}\t课程五:{}\t课程六:{}\n".format(i16, i17, i181, i182, i183,
                                                                                           i184, i185, i186)
        ss = "学生:{}的选课信息已经保存成功!(D://课程//学生选课信息.txt)\n".format(i16)
        sss = "学生:{}所选的课程包含未录入课程或未选满课程!\n".format(i16)
        ssss = "学生:{}对应的学号已经存在!\n".format(i16)
        # 判断总分之和是否大于60分数  这个功能太监了
        if i16:  # 排除空值
            if i17:  # 判空
                if str(i17) in nl:  # 判断输入的学号是否已存在
                    text3.insert(END, ssss)

                if str(i181) and str(i182) and str(i183) and str(i184) and str(i185) and str(
                        i186) in class_list:  # 判断课程是否存在
                    with open("D://课程//学生选课信息.txt", "a") as of:
                        of.write(s)
                        of.close()
                        text3.insert(END, ss)  # 显示追加效果
                        ip16.delete(0, END)  # 清空输入
                        ip17.delete(0, END)  # 清空输入
                        ip181.delete(0, END)  # 清空输入
                        ip182.delete(0, END)  # 清空输入
                        ip183.delete(0, END)  # 清空输入
                        ip184.delete(0, END)  # 清空输入
                        ip185.delete(0, END)  # 清空输入
                        ip186.delete(0, END)  # 清空输入
                else:  # 追加其他信息
                    text3.insert(END, sss)  # 显示追加效果


查询课程:

在这里插入图片描述
解析:这里我想到二种查询方式,二个确定分别对应二个按钮的传送位置,同样,我这些都是用子窗口创建的,基本操作都一样,就是控件多了点,理解起来很容易,就是遍历文件,查询下输入的信息对应的是文件的哪行,然后输出到text里面就行了,最后清空一下输入框,我相信你们。
代码:

def find():  # 查询函数
    print("查询")
    winNew4 = Toplevel()
    winNew4.geometry(align_str)  # 设置窗口大小 和原窗口一致
    winNew4.resizable(width=True, height=True)
    # 设置窗口是否可变长、宽,True:可变,False:不可变
    winNew4.title('查询信息模式')
    label_a = Label(winNew4, text="学生选修课程系统设计", bg="#00BFFF", fg="red", font=("宋体", 30), relief=GROOVE).pack()
    label_b = Label(winNew4, text="---------请开始选择课程之旅!---------", font=("宋体", 20)).pack()
    # 定义上面的窗口界面
    # 定义下面二种查询方式   通过姓名查询  或者通过课程查询  其他方式没想到
    label_19 = Label(winNew4, text="按学生姓名查询:", font=("宋体", 10))
    label_19.place(relx=0.25, rely=0.3)
    label_20 = Label(winNew4, text="按学生学号查询:", font=("宋体", 10))
    label_20.place(relx=0.25, rely=0.4)
    # 定义二个输入输入框
    inp19 = Entry(winNew4)
    inp19.place(relx=0.45, rely=0.3)  # 学生姓名传值
    inp20 = Entry(winNew4)
    inp20.place(relx=0.45, rely=0.4)  # 学生学号传值
    # 定义二个确定按钮
    btn4 = Button(winNew4, text="确定", command=lambda: namefind(inp19.get(), inp19, text4))  # 学生姓名确定
    btn4.place(relx=0.75, rely=0.28)
    btn5 = Button(winNew4, text="确定", command=lambda: classfind(inp20.get(), inp20, text4))  # 学生学号确定
    btn5.place(relx=0.75, rely=0.39)
    # 写一个备注ps
    ps = Label(winNew4, text="PS:若文本框未显出信息,则该学生选课信息未成功保存,请重试!", font=("宋体", 10))
    ps.place(relx=0, rely=0.52)
    # 定义一个关闭按钮
    btClose4 = Button(winNew4, text='关闭', command=winNew4.destroy)  # 取消按钮
    btClose4.place(relx=0.75, rely=0.5)
    # 定义下面的文本框
    text4 = Text(winNew4, bg="#d3fbfb")
    text4.place(rely=0.6)


代码 姓名查询:

def namefind(i19, inp19, text4):  # 按照学生姓名查询文件 然后返回到find定义的文本框中
    print(i19)  # 检验传值是否成功
    with open("D://课程//学生选课信息.txt", "r") as ff:  # 遍历这个txt把
        for i in ff:  # 遍历文件的每一行 进行判断
            if i19:  # 判空
                if str(i19) in i:
                    text4.insert(END, i + '\n')
                    inp19.delete(0, END)

代码 学号查询:

def classfind(i20, inp20, text4):  # 按照学生学号来查询,
    print(i20)  # 检验传值是否成功
    with open("D://课程//学生选课信息.txt", "r") as ff:  # 遍历这个txt把
        for i in ff:
            if len(str(i20)) == 4:  # 判断这个学号真的是学号
                if str(i20) in i:  # 判断学号是否在选课信息
                    text4.insert(END, i + "\n")
                    inp20.delete(0, END)


主函数:

其他的函数块,我上面都给了,全部填入就能实现:

from tkinter import *
import time
import os
def menu(var):  # 菜单返回函数
    print(var)  # 检测函数返回值
    if var == 0:
        luru()  # 录入函数
    elif var == 1:
        look()  # 课程浏览
    elif var == 2:
        choose()  # 课程选择
    else:
        find()  # 课程查询

后记:

愿世间再无2020,你我只顾向前奔波,朝着自己前进的方向走就是!

在这里插入图片描述

发布了14 篇原创文章 · 获赞 276 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_45906219/article/details/105396699