百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

Python GUI项目实战(四)实现学生明细窗体GUI的设计

off999 2024-12-25 14:47 43 浏览 0 评论

前言

在上一节Python GUI项目实战(三)实现信息查询功能 我们实现了在主窗体中通过单条件查询或者组合查询进行学生信息的筛选功能,系统能够在所有的数据中精确地找到某个具体的符合条件的学生信息。但是我们发现在主窗体中显示的都是概要信息,如果我们想要鼠标双击表格中的某一项就想查看某个学生的详细信息该怎么实现呢?

这一节我们将搭建一个显示学生详细信息的明细窗体,显示该学生的所有信息,只要双击表格中的某一行就能打开。同时显示学生明细信息时我们的明细窗体要表现出三种不同的状态,同时应对显示、添加、和修改三种情况。在不同的状态下窗体显示的得标题是不同的。我们现在就开始着手操作吧这个项目吧~


一、学生明细窗体GUI基本布局

我们新建一个detailgui.py文件,显示学生明细信息。主要显示的内容有:学号、姓名、性别、出生日期、身份证号码、手机号码、邮箱地址、家庭住址、入学时间、专业、紧急联系人、紧急联系电话;其中性别我们通过Radiobutton的方式显示,其余都通过Label和Entry来显示。

本文重点讲解的内容是逻辑与实现部分;关于tkinter布局的基础知识,这里主要用到的主要是Label标签和Entry输入框还有Radiobutton单选框的绘制,我们前面的文章Python基础学习笔记(十三)图形化界面Tkinter 已经做了具体的讲解,这里就不再继续重复介绍了。

下面直接给出界面布局的代码:

from tkinter import *
from tkinter.ttk import *
import os

class DetailWindow(Tk):
    def __init__(self):
        super().__init__()
        self.title("学生明细信息")
        self.geometry("600x500+600+150")
        self.resizable(0,0) # 不能改变大小

        # 加载控件
        self.setup_UI()

    def setup_UI(self):
        # 设置style
        self.Style01 = Style()
        self.Style01.configure("title.TLabel",font=("微软雅黑",25,"bold"),foreground = "navy")
        self.Style01.configure("TLabel", font=("微软雅黑", 16, "bold"), foreground="navy")
        self.Style01.configure("TButton",font=("微软雅黑",16,"bold"),foreground = "navy")
        self.Style01.configure("TEntry", font=("微软雅黑", 16, "bold"),width = 10)
        self.Style01.configure("TRadiobutton",font=("微软雅黑",16,"bold"),foreground = "navy")
        # 加载上面的banner
        self.Login_image = PhotoImage(file = "."+os.sep+"img"+os.sep+"stu_detail_banner.png")
        self.Label_image = Label(self,image = self.Login_image)
        self.Label_image.pack()

        # 添加一个title
        self.var_title = StringVar()
        self.Label_title = Label(self,text="==明细窗体==",style = "title.TLabel")
        self.Label_title.place(x=380,y=20)

        # 加载一个pane
        self.Pane_detail = PanedWindow(width = 590,height = 380)
        self.Pane_detail.place(x = 5,y = 88)

        # 添加属性
        # 第一排:学号
        self.Label_sno = Label(self.Pane_detail,text = "学号:")
        self.Label_sno.place(x=30,y=10)
        self.var_sno = StringVar()
        self.Entry_sno = Entry(self.Pane_detail,textvariable = self.var_sno,font=("微软雅黑", 16, "bold"),width = 10)
        self.Entry_sno.place(x=80,y=8)
        # 姓名
        self.Label_name = Label(self.Pane_detail,text = "姓名:")
        self.Label_name.place(x=220,y=10)
        self.var_name = StringVar()
        self.Entry_name = Entry(self.Pane_detail,textvariable = self.var_name,font=("微软雅黑", 16, "bold"),width = 10)
        self.Entry_name.place(x=270,y=8)
        # 性别
        self.Label_gender = Label(self.Pane_detail,text = "性别:").place(x=410,y = 10)
        self.var_gender = IntVar()
        self.Radio_man = Radiobutton(self.Pane_detail,text="男",variable = self.var_gender,value = 1)
        self.Radio_man.place(x=460,y = 10)
        self.Radio_woman = Radiobutton(self.Pane_detail, text="女", variable=self.var_gender, value=0)
        self.Radio_woman.place(x=510, y=10)
        # 第二排:出生日期
        self.Label_age = Label(self.Pane_detail,text="出生日期:")
        self.Label_age.place(x=30,y=60)
        self.var_age = StringVar()
        self.Entry_age = Entry(self.Pane_detail,textvariable = self.var_age,font=("微软雅黑", 16, "bold"),width = 12)
        self.Entry_age.place(x=110,y=58)
        # 身份证号码
        self.Label_id = Label(self.Pane_detail, text="身份证号码:")
        self.Label_id.place(x=250, y=60)
        self.var_id = StringVar()
        self.Entry_id = Entry(self.Pane_detail, textvariable=self.var_id,font=("微软雅黑", 16, "bold"), width=19)
        self.Entry_id.place(x=350, y=58)
        # 第三排:手机号码
        self.Label_mobile = Label(self.Pane_detail, text="手机号码:")
        self.Label_mobile.place(x=30, y=110)
        self.var_mobile = StringVar()
        self.Entry_mobile = Entry(self.Pane_detail, textvariable=self.var_mobile,font=("微软雅黑", 16, "bold"), width=14)
        self.Entry_mobile.place(x=110, y=108)
        # 邮箱地址
        self.Label_email = Label(self.Pane_detail, text="邮箱地址:")
        self.Label_email.place(x=270, y=110)
        self.var_email = StringVar()
        self.Entry_email = Entry(self.Pane_detail, textvariable=self.var_email,font=("微软雅黑", 16, "bold"), width=19)
        self.Entry_email.place(x=350, y=108)
        # 第四排:家庭住址
        self.Label_home = Label(self.Pane_detail, text="家庭住址:")
        self.Label_home.place(x=30, y=160)
        self.var_address = StringVar()
        self.Entry_home = Entry(self.Pane_detail, textvariable=self.var_address,font=("微软雅黑", 16, "bold"), width=43)
        self.Entry_home.place(x=110, y=158)
        # 第五排:入学时间
        self.Label_studyin = Label(self.Pane_detail, text="入学时间:")
        self.Label_studyin.place(x=30, y=210)
        self.var_studyin = StringVar()
        self.Entry_studyin = Entry(self.Pane_detail, textvariable=self.var_studyin,font=("微软雅黑", 16, "bold"), width=12)
        self.Entry_studyin.place(x=110, y=208)
        # 专业:
        self.Label_pro = Label(self.Pane_detail, text="专业:")
        self.Label_pro.place(x=250, y=210)
        self.var_pro = StringVar()
        self.Entry_pro = Entry(self.Pane_detail, textvariable=self.var_pro,font=("微软雅黑", 16, "bold"), width=24)
        self.Entry_pro.place(x=300, y=208)
        # 第六排:紧急联系人
        self.Label_emcon = Label(self.Pane_detail, text="紧急联系人:")
        self.Label_emcon.place(x=30, y=260)
        self.var_emcon = StringVar()
        self.Entry_emcon = Entry(self.Pane_detail, textvariable=self.var_emcon,font=("微软雅黑", 16, "bold"), width=11)
        self.Entry_emcon.place(x=120, y=258)
        # 紧急联系电话
        self.Label_emtel = Label(self.Pane_detail, text="紧急联系人电话:")
        self.Label_emtel.place(x=250, y=260)
        self.var_emtel = StringVar()
        self.Entry_emtel = Entry(self.Pane_detail, textvariable=self.var_emtel,font=("微软雅黑", 16, "bold"), width=16)
        self.Entry_emtel.place(x=380, y=258)
        # 放置两个按钮
        self.Button_save = Button(self,text = "保存",style = "TButton").place(x=400,y=472)
        self.Button_exit = Button(self,text = "关闭",style = "TButton").place(x=502,y=472)
if __name__ == '__main__':
    this_window = DetailWindow()
    this_window.mainloop()

效果演示:

二、加载明细窗体

加载学生明细信息我们应该设置三种状态:查看、添加、修改;

1. 功能需求

  • 在查看状态下,标题是:查看学生明细,各信息栏输入框中所有的信息都是只读状态,并且右下角的保存按钮处于隐藏状态;
  • 在添加状态下,标题是:添加学生明细,各信息栏输入框清空,右下角保存按钮可用;
  • 在修改状态下,标题是:修改学生明细,各信息栏除学号不能修改外,其余信息栏均可修改,并且右下角保存按钮可用。

2. 触发条件

我们实现查看学生明细信息的三种状态的触发条件:

3. 遇到问题

为了能查看学生明细信息,我们要在主窗体中定义一个函数load_detail_window(),在此之前我们要导入detailgui模块,调用DetailWindow类;

import detailgui
def load_detail_window(self):
    detail_window = detailgui.DetailWindow()

接着,我们再定义一个add_student的函数,在这个函数中调用load_detail_window方法

def add_student(self):
    self.load_detail_window()

然后在按钮中添加command参数,其值为add_student; 这样做似乎貌似实现了简单的加载学生明细窗体的功能,实际上当我们执行程序,点击添加学生按钮后,系统会报错

_tkinter.TclError: image "pyimage4" doesn't exist

这是什么原因呢?

在tkinter里面有一个类Tk,其功能是产生一个主窗体,我们前面每次创建窗体时都用到了它。但是在tkinter里有一个规定,应用程序同时只能运行一个主窗体。而这里我们的主窗体一直在运行,是没有办法再加载一个主窗体(明细信息)的。如果想同时加载两个窗体,第二个窗体必须要以子窗体的形式打开,这里我们就可以使用Toplevel来创建子窗体。

所以,detialgui的DetailWindow类所继承的类应该由Tk,换成Toplevel即可。 这时候又出现了一个小bug,pane与明细窗体发生了脱离,这是因为我们前面创建pane容器的时候忘记设置它的属主了,这里添加一个构建函数中添加一个self参数就可以了。现在点击添加学生按钮,就可以正常加载明细信息窗口了!

所以,出现这个问题的根源所在就是:使用Tk这个类实例化一个窗体,这个窗体是一个主窗体。已经实例化了一个主窗体,再实例化一个是不可以的。所以第二个窗体必须用Toplevel实例化。

三、实现三种状态加载明细窗体

1. 点击按钮触发

前面我们已经实现了添加明细信息的功能,现在我们继续实现修改明细信息的功能。我们新定义一个update_student()函数:

def update_student(self):
    self.load_detail_window()

然后在修改学生按钮中添加command参数即可。

2. 双击表格触发

我们想双击TreeView中的某一行表格,就能触发查看明细信息的功能,首先我们定义一个查看明细信息的方法view_student(),由于双击是一个事件,所以在调用函数的时候需要添加一个参数event

def view_student(self,event):
    self.load_detail_window()

然后在 setup_UI()函数的结尾处,添加触发双击表格某一行的事件,写法是:使用bind()方法,第一个参数一定要以Double开头,体现是一个双击事件,第二个函数为对应的触发函数。

self.Tree.bind("<Double-1>",self.view_student)

效果演示:

四、呈现三种不同的状态

以上三种触发函数实现的都是同一种功能,然而我们想实现查看、添加、修改三种不同状态,那么怎样才能体现差异化呢?

1.添加标志参数

在实例化明细窗体的时候,添加一个标志参数action_flag,我们通过区分action_flag参数的值,来确定以什么样的模式进行加载。 这里我们规定:

  • 当action_flag = 1时,表示查看模式;
  • 当action_flag = 2时,表示添加模式;
  • 当action_flag = 3时,表示修改模式。

2. 修改窗体标题

我们在明细窗体的构造函数中,定义一个全局变量:

self.flag = action_flag

再定义一个修改窗体标题的函数:

def load_windows_flag(self):
    if self.flag == 1:
        self.Label_title.configure(text="==查看学生明细==")
    elif self.flag == 2:
        self.Label_title.configure(text="==新建学生明细==")
    elif self.flag == 3:
        self.Label_title.configure(text="==修改学生明细==")

创建好修改标题的函数后,不要忘了在构造函数中添加上:

self.load_windows_flag()

我们在主窗体函数中也定义一个全局变量,作为修改明细窗体标题的标志位:

self.action_flag = 0

然后在主窗体函数中,给load_detail_window()函数添加参数self.action_flag:

def load_detail_window(self):
    detail_window = detailgui.DetailWindow(self.action_flag)

与此同时,add_student()、update_student()、view_student()三个方法也要做相应的修改:

def add_student(self):
    self.action_flag = 2
    self.load_detail_window()

def update_student(self):
    self.action_flag = 3
    self.load_detail_window()

def view_student(self,event):
    self.action_flag = 1
    self.load_detail_window()

这样三种不同的触发事件,对应的明细窗体标题也发生了相应的变化:

点击添加学生按钮,明细窗体标题显示“添加学生明细”;点击修改学生按钮,明细窗体标题显示“修改学生明细”;双击表格学生学生信息某一行,明细窗体标题显示“查看学生明细”。

最后

本节我们完成了明细窗体GUI的搭建,设置了明细窗体的查看模式、添加模式、和修改模式,并且实现了在不同触发按钮下同一个明细窗体显示不同的标题。希望小伙伴们不仅仅学习的同时,思考一下为什么要这么做?我们是怎么实现呈现三种不同窗体状态的,并且结合着前面的文章自己动手练一练,所有的数据源、素材和源码直接私信我,我发给你。

本节的明细窗体GUI的搭建已经完成了,前期准备工作已经做好了,下一节我们就要正式将数据源学生信息填充进明细窗体中显示出来,敬请期待吧~

小伙伴们觉得文章内容还不错的话,点赞、转发、关注安排一下^_^,感谢您的支持~

相关推荐

无敌系统流小说(无敌系统流的小说)

《嫡女之花开富贵》作者:伊人睽睽简介祖父是镇国将军,贵不可言;外公是帝师,才名满天下;父母亲琴瑟和鸣,恩爱无双,无妾室插足;穿越为书香门第的嫡小姐,且无任何庶兄妹,慕兰音认为,她这一生,必将佳期如梦...

键盘上windows键是哪个键(电脑键盘上windows键是哪个)
键盘上windows键是哪个键(电脑键盘上windows键是哪个)

一、台式机键盘。Windows键,简称“Winkey”或“Win键”,是在计算机键盘左下角Ctrl和Alt键之间的按键,台式机全尺寸键盘的主键盘区左下角和右下角各有一个,图案是MicrosoftWindows的视窗徽标。二、笔记...

2026-01-13 11:51 off999

笔记本电脑必备app(笔记本电脑必备管宿)
  • 笔记本电脑必备app(笔记本电脑必备管宿)
  • 笔记本电脑必备app(笔记本电脑必备管宿)
  • 笔记本电脑必备app(笔记本电脑必备管宿)
  • 笔记本电脑必备app(笔记本电脑必备管宿)
桌面图标设置在哪打开(桌面图标从哪里调出)
桌面图标设置在哪打开(桌面图标从哪里调出)

1、首先来到电脑桌面,此时桌面没有任何图标,如下图所示。2、我们先右键单击任务栏,会出现工具栏,这时我们在下拉的选项里选择“快速启动”按钮。3、单击快速启动按钮后会出现如图所示情况,这时在电脑屏幕的左下方会显示很多快捷按钮,一般情况下单击快...

2026-01-13 10:51 off999

windows如何进入启动项(怎么进入启动选项)

方法步骤如下:1.点击应用在Windows设置界面点击应用选项进入。2.选择启动在左侧分类中选择启动选项。3.点击开关点击软件后方的开关即可启动或关闭开机启动项。1、在Window的文件资...

win11下载安装

一、允许安装软件1、首先点击左下角的开始按键,然后点击“settings”进入设置。2、然后点击设置中的“应用”选项。3、在点击左侧任务栏中的“应用和功能”。4、点击下拉栏,然后选择其中的“任何来源”...

win7支持的最高配置(win7支持的最高配置是多少)

答案是支持win7的最高配置应该是i99900k加b365主板。 不过这套配置市面上价格偏高。这种机器比同等酷睿13代处理器的价格还要高至少一千元以上。而且就性能而言要超过i99900...

指令引用的内存不能为read(指令引用的0x0000000内存.该内存不能为read)

出现“指令引用内存不能为read”的错误可能有多种原因,包括软件冲突、驱动问题、内存质量问题等。以下是一些可能的解决方案:1.检查是否有软件冲突:尝试关闭可能冲突的软件,例如杀毒软件、优化软件等。2...

hp1010打印机驱动程序(hp deskjet1010打印机驱动)

1.把光盘到电脑里然后打开光盘找到“setup.exe”双击运行。2.这里点击“不用了,谢谢,我喜欢CD安装”;下载的驱动也点这个。3.到这个一步有6个软件需要安装,不用点选直接下一步即可。4.同意服...

电脑黑屏怎么关机(电脑黑屏怎么关机不会伤硬盘)

开机按F8不动到高级选项出现在松手,选“最近一次的正确配置”回车修复,还不行按F8进入安全模式还原一下系统或重装系统(如果开机没反应,放一下电,重新插拔一下硬件,如果总是开不了机就检修一下去)。如果是...

应用程序无法启动0xc0000005

4、设备主板故障也会导致无信号,建议联系专业的维修人员上门检修。5、设备显卡手指边与手指边插槽接触不良,清理一下显卡的金手指边,重新插回去,重新固定住即可。应用程序错误0xc0000005解决方法如下...

移动硬盘分区方法详解(移动硬盘分区步骤)

1、进入管理页面将新买的移动硬盘插入计算机的USB接口,右击此电脑后选择管理。2、选择压缩卷在页面里选择“磁盘管理”,右击移动硬盘,选择“压缩卷”。3、输入压缩空间的大小输入压缩空间的大小,点击右下角...

windows7副本不是正版影响使用吗

会经常弹出提示和安全警告,如果我们安装了一个非正版的windows系统,就会经常弹出此windows副本不是正版的提示,那么此windows副本不是正版有什么影响呢,其实除了视觉外,功能也会有影响。w...

100个有效qq号以及密码2025(2021最新qq号和密码大全)
100个有效qq号以及密码2025(2021最新qq号和密码大全)

有关QQ登记全国之最的数据目前并没有最新数据更新,最新的该项数据是截止于2019年12月的数据,接下来为大家带来QQ等级全国第一的用户的有关数据,仅供大家娱乐之用:截止2019年12月,全国qq等级第一名的名字叫做“小风波”,QQ等级高达1...

2026-01-13 05:51 off999

联想window7(联想windows7怎么设置锁屏时间)
  • 联想window7(联想windows7怎么设置锁屏时间)
  • 联想window7(联想windows7怎么设置锁屏时间)
  • 联想window7(联想windows7怎么设置锁屏时间)
  • 联想window7(联想windows7怎么设置锁屏时间)

取消回复欢迎 发表评论: