Skip to content

前言

上一节,我们已经实现类数据从文本文件中读取,以及加载显示在表格中,这一节我们要继续实现的内容是双击表格显示查看明细信息,选中某一条学生信息后点击修改按钮可以弹出修改学生明细信息的界面。点击添加按钮可以添加信息,点击删除按钮不弹出明细窗口,但是能通过对话框删除信息。

part4 加载明细窗体

一、以三种状态加载明细窗体

1. 需求分析

实现三种状态:

三种状态 输入框属性 标题 按钮情况 触发条件
查看 只读 查看学生明细 只有关闭按钮 双击某一行数据
修改 除了学号,所有数据都可以修改 修改学生明细 有保存和关闭按钮 选中某一行数据,点击修改按钮
添加 所有的输入框为空 修改学生明细 有保存和关闭按钮 直接点击“添加”按钮
2. 实现方法

如何实现以三种不同状态来加载明细窗体呢?其实我们前面也做过类似案例,在加载明细窗体的时候携带一个参数flag,通过参数的值判断是添加、修改、还是查看。 在studentdetail这个类的初始化方法中添加一个int型的flag参数,并且在本地接收这个参数,判断这个参数的值。

self.flag = flag
这里我们提前规定: | flag值的情况 | 属性窗体设置情况 | | :----------: | :--------------: | | flag==1 | 查看学生明细窗口 | | flag==2 | 修改学生明细窗口 | | flag==3 | 添加学生明细窗口 |

(1)明细窗体做接受flag参数准备 我们定义一个方法load_gui_by_flag目的为了根据不同flag的值加载不同的GUI状态,暂时先做修改标题的功能。

def load_gui_by_flag(self):
    if self.flag == 1:
        # 窗口为查看的状态
        self.Label_Title["text"] = "查看学生明细"
    elif self.flag == 2:
        # 窗口为修改状态
        self.Label_Title["text"] = "修改学生明细"
    elif self.flag == 3:
        # 窗口为添加的状态
        self.Label_Title["text"] = "添加学生明细"
同时也不要忘了将这个方法,添加到初始化方法中,用来自动执行。 好了,这边学生明细窗口已经做好接收flag参数的准备了,我们在主窗体界面下该怎么触发相应事件来传递flag参数呢? (2)主窗体做好事件触发传递flag参数 实际上,添加一个表格选项双击事件需要用表格对象调用bind方法,<Double-1>代表双击事件。
self.Tree_student.bind("<Double-1>", self.view_student)
接下来再定义一个打开窗体的方法view_student来打开学生明细窗体。 注意:这里定义的view_student方法,需要多添加一个参数event否则无法打开。
def view_student(self,event):
    """
    双击某一行,加载明细信息
    """
    # 以查看的形式加载
    detail = StudentDetail(1)
(3)给按钮添加功能 分别给添加按钮和删除按钮加上command参数,其值分别为相应的方法。我们定义add_student方法,给StudentDetail传递参数3,定义update_student方法,给StudentDetail传递参数2。 这里我们先只写出方法雏形,接下来我们会继续完善。

二、数据表示

1. 需求分析

我们在记录和表示教师信息的时候有若干个字段,我们在传递数据的时候如果提供这么多参数会很麻烦,我们看能不能把这若干个参数封装成一个实体类。

2. 实现过程

我们在Service文件夹下新建一个person.py文件,定义一个Person实体类

class Person:
    def __init__(self, name, gender, birthday, mobile, email):
        self.name = name
        self.gender = gender
        self.birthday = birthday
        self.mobile = mobile
        self.email = email
接着再通过Person这个类来派生出Student类和Teacher类。
# 派生类 --- Student
class Student(Person):
    def __init__(self, name, gender, birthday, mobile, email, sno, profession, study_time):
        super().__init__(name, gender, birthday, mobile, email)
        self.sno = sno
        self.profession = profession
        self.study_time = study_time
后面我们如果表示一个学生或者老师,直接实例化一个类的对象即可,这个对象即包含了下面所有的参数。

三、 查看学生明细信息

1. 需求分析

实现查看学生明细信息的窗口的绘制,我们需要满足的条件有: (1)修改Title为“查看学生明细” (2)隐藏保存按钮 (3)把双击的那行数据的填充到Entry (4)禁用所有的Entry (5)给按钮添加对应的功能

2. 实现过程

我们需要写的操作需要在studentdetail.pyload_gui_by_flag方法下完成。 (1)修改标题前面已经讲过了,实现方法为:

self.Label_Title["text"]="查看学生明细"
(2)隐藏保存按钮,由于我们的Button_savebasedetail使用palce的方式布局的,所以这里我们使用place_forget()方法对其进行隐藏。
self.Button_save.place_forget()
(3)把双击选中的数据填充到Entry,我们要把数据传过来,这个数据怎么传过来呢?实现两个窗体之间的数据传递最基本的方法就是通过构造函数。所以我们的StudentDetail类的构造函数除了要有flag参数外,我们还应该添加一个参数current_student,然后在该类中接收这个参数的值。
class StudentDetail(BaseDetail):
    def __init__(self, flag: int, current_student):
        super().__init__()
        self.flag = flag
        self.current_student = current_student
于是,我们在主窗体中查看学生信息的方法view_student还需要添加功能以获取点击的内容。 首先我们需要在构造函数里提前添加一个空列表用来存储表格中被选中的学生。
self.student_current = []
以及定义flag变量来标记窗口状态
self.flag = 0
最后完善view_student函数,获取表格中双击的某一行的第一个数item然后根据item获取表格中存储的学生信息。
def view_student(self,event):
    """
    双击某一行,加载明细信息
    """
    # 获取点击的当前行
    item = self.Tree_student.selection()[0]  # 表示获取的当前行数据的第一个数
    current_student = self.Tree_student.item(item, "values")    # 根据id取出values

    for item in self.student_all:
        if current_student[0] == item[0]:
            self.student_current = item

    # 修改flag
    self.flag = 1

    # 以查看的形式加载
    detail = StudentDetail(self.flag, self.student_current)
主窗体中数据已经准备好传递了,studentdetail窗体现在开始准备接收数据。 以填充学生学号为例,我们需要先定义个存储学号的变量var_sno,然后给输入学号的Entry添加这个属性。我们才能在后面对这个Entry进行赋值。
self.var_sno = StringVar()
self.Entry_sno = Entry(self.Pane_detail, textvariable=self.var_sno, font=("微软雅黑",13),width=12)
我们在load_gui_by_flag中,填充数据时直接使用set方法即可。
self.var_sno.set(self.current_student[0])
这样我们就完成了,双击表格的某行,在明细窗口对学号的传递。 1.gif 其余的组件也是同样的方法,以此类推。
self.var_sno.set(self.current_student[0])
self.var_name.set(self.current_student[1])
# 性别选项是Radio,需要判断一下。
if "男" in self.current_student[2]:
    self.var_gender.set(1)
else:
    self.var_gender.set(2)
self.var_birthday.set(self.current_student[3])
self.var_mobile.set(self.current_student[4])
self.var_email.set(self.current_student[5])
self.var_profession.set(self.current_student[6])
self.var_entry_time.set(self.current_student[7])
效果演示: 1.gif

(4)禁用输入框 由于我们打开的是查看窗口,所以所有的输入框都应该是禁用状态。 输入框Entry里有一个state属性,我们给它赋一个值DISABLED这个组建就被禁用了,显示成一个灰色

self.Entry_sno["state"] = DISABLED  # 以禁用学生学号输入框为例,其它以此类推。
把剩下的所有输入框都禁用后: 效果演示: 图片.png (5)给关闭按钮添加功能 由于我们定义的关闭按钮是在模板中创建的,所以我们先回到创建模板的basedetail.py,定义一个关闭当前GUI的函数close_gui,然后给关闭按钮添加一个command参数,再把close_gui作为值赋给command参数即可。
def close_gui(self):
    self.destory()
至此,我们的关闭功能也实现了,学生明细窗口基本完成了。

最后

本节,我们实现了查看明细窗体的功能,下一节,我们将定义一个Service类,以实现校验、修改、添加、删除和保存的功能。