综合案例四 学生选课系统
【实验目的与要求】
1.熟练使用VFP的操作环境
2.熟练使用项目管理器管理各种文件
3.掌握数据库的设计方法和步骤
4.熟练掌握数据库表及其表之间关系的创建与使用
5.掌握查询与视图的创建与使用
6.掌握程序设计的基本方法
7.掌握表单及其表单中各种控件的设计与使用
8.掌握菜单的创建和使用
【实验要求】
(1)能输入、修改、查询选课有关的信息,如学生档案、课程信息、教师信息、成绩信息等;
(2)能进行统计,如学生选修课程的平均成绩、某课程的平均成绩。
(3)能打印学生成绩单、教师工作量表等。
用户提出开发应用系统的要求后,软件开发者应通过调查研究归纳出目标系统的数据需求和功能需求。
(一)数据需求
通过调查,总结出用户对数据的需求如下:
(1)学生信息
包括:学生姓名、性别、出生日期、是否团员、专业、入学时间、入学成绩、简历、照片等。
(2)课程信息
包括:课程名称、课程性质、学时数、学分等。
(3)教师信息
包括:教师姓名、性别、职称、通信地址、电话、电子信箱等。
(4)选课信息
包括:学生姓名、课程名称、开课时间、成绩等。
(二)功能需求
功能分析的任务是了解用户对数据的处理方法和输出格式。
1.基础数据录入
基础数据包括学生数据、课程数据、教师数据和学生选课数据以及编码数据等。要求系统能录入这些数据,并且能够进行修改。注意在数据录入和修改的过程中应保持数据的参照完整性。
2、查询
能够查询出学生数据、课程数据、教师数据以及学生选课数据等。
3、统计
要求能根据学生选课信息按学生统计平均成绩和按课程统计平均成绩。
4、打印输出
打印学生成绩单和教师工作量表。
【概要设计】
Ø 项目设计
一个典型的数据库应用程序有数据结构、用户界面、查询选项和报表组成。在设计应用程序时,应仔细考虑每个组件将提供的功能以及与其他组件之间的关系。
一个经过良好组织的Visula FoxPro应用程序一般需要为用户提供菜单;一个或多个表单,供数据输入并显示。同时还需要添加某些事件响应代码,提供特定的功能,保证数据的完整性和安全性。此外,还需要提供查询和报表,允许用户从数据库中选择信息。
Visual FoxPro提供的项目管理器作为集成管理各相关组件的组织工具,并把它们编译为单个应用文件。使用项目管理器创建一个项目后,就可以应用程序已具备一个开发框架了,下一步的工作就是如何在这个框架之下利用项目管理器所提供的强大功能,按照需求来实现应用程序所要求的功能。
1.建立“学生选课系统“项目
为快速建立一个应用程序及其项目,即一个完整“应用程序框架”的项目,可以使用“应用程序向导”,在项目建立后,便打开了应用程序生成器。也可以使用“新建文件”,弹出创建对话框,指定项目及其组件的存储路径为“C:¥ 学生选课系统”,项目名为“学生选课系统”。
2.设置主文件
当用户运行应用程序时,Visual FoxPro将启动主文件,然后主文件再依次调用所需要的应用程序其他组件。一般最好的方法是为应用程序建立一个主程序。但是,使用一个表单作为主程序,可以将主程序的功能和初始界面集成在一起。
本项目设置主文件为程序文件“主程序”,如图1所示。
方法:在“主程序”上单击鼠标右键,选中“设置主文件”菜单项,或先选中“主程序”,单击“项目”菜单,选中选中“设置主文件”菜单项。
例如,主文件代码编写如下:
clear all
set talk off
set default to c:¥学生选课系统¥ && 设置程序的默认路径
public xh,jsbh,kcbh && xh、jsbh、kcbh分别用于存储输入的学号、
&&教师编号、课程编号
do form 封面 && 调用封面程序
modify window screen title '学生选课管理系统' && 设置主窗口的标题
do 主菜单.mpr && 调用出菜单
read event && 建立时间循环
quit && 退出VFP
图1 设置项目的主文件
Ø 数据库的设计
数据库设计的任务是确定系统所需的数据库。数据库是表的集合,通常一个系统只需一个数据库。数据库的设计一般可分为逻辑设计和物理设计两步。逻辑设计的任务是根据需求分析,确定数据库所包含的表及字段、表间的关系,物理设计就是具体确定表的结构,包括字段名、字段类型及宽度,需要的索引等。
(一)逻辑设计
根据对需求得到的数据结构进行分析,按数据输入输出的要求,确定表和表间的关系,并进行验证、调整、修改、完善,使其能够实现用户对数据和功能的要求。本例根据分析确定系统要设置如下表:
(1)学生基本表,包括字段:学号、姓名、性别、出生日期、是否团员、照片、入学时间、入学成绩、专业编号、简历。学号为主索引,为专业编号建立索引,通过该索引和专业基本表建立关联。
(2)教师基本表,包括字段:教师编号、教师姓名、性别、职称、电话、通讯地址、邮政编码、电子信箱。教师编号为主索引。
(3)课程基本表,包括字段:课程编号、课程名称、课程性质、学时、学分、备注。课程编号为主索引。
(4)学生选课表,字段包括:学号、课程编号、开课时间、成绩。学生、课程编号和开课时间共同做主索引,分别为学号、课程编号、开课时间、成绩建立索引,通过学号和学生基本表建立关联,通过课程编号和课程基本表建立关联,开课时间和成绩索引用于做统计计算。
(5)教师任课表,包括字段:教师编号、课程编号。分别为教师编号和课程编号建立索引,通过教师编号和教师基本表建立关联,通过课程编号和课程基本表建立关联。
(6)专业表,字段包括:专业编号、专业名称、所属系、备注。为专业编号建立索引,通过专业编号和学生基本表建立关联。
(二)物理设计
下面列出选课系统所有表的结构和索引,为了便于理解,将部分数据列出。
1.学生基本表
表名:学生
结构:
字段名 | 类型 | 宽度 | 小数位数 | 索引 |
学号 | 字符型 | 12 |
| 主索引 |
姓名 | 字符型 | 8 |
|
|
性别 | 字符型 | 2 |
|
|
出生日期 | 日期型 |
|
|
|
是否团员 | 逻辑型 |
|
|
|
照片 | 通用型 |
|
|
|
入学时间 | 日期型 |
|
|
|
入学成绩 | 数值型 | 3 | 0 |
|
专业编号 | 字符型 | 4 |
| 普通索引 |
简历 | 记忆型 |
|
|
|
记录:
学号 | 姓名 | 专业编号 | 性别 | 出生日期 | 入学时间 | 入学成绩 | 团员否 |
200010301001 | 谢胜 | 03 | 男 | 1980-10-23 | 2000-9-1 | 589 | TRUE |
200010301020 | 张辉 | 03 | 男 | 1981-5-20 | 2000-9-1 | 608 | TRUE |
200020302045 | 陈诚 | 03 | 男 | 1980-8-4 | 2000-9-1 | 598 | TRUE |
200034201002 | 刘玫 | 42 | 女 | 1980-9-4 | 2000-9-1 | 567 | FALSE |
200034202123 | 李丹 | 42 | 女 | 1981-3-5 | 2000-9-1 | 601 | TRUE |
199920403128 | 胡广飞 | 04 | 男 | 1980-4-6 | 1999-9-1 | 521 | FALSE |
199924104112 | 廖荣化 | 41 | 男 | 1980-10-31 | 1999-9-1 | 534 | FALSE |
199934205255 | 赵雅娟 | 42 | 女 | 1980-7-8 | 1999-9-1 | 546 | TRUE |
200010401081 | 李文浩 | 04 | 男 | 1981-9-20 | 2000-9-1 | 638 | TRUE |
200010401032 | 陶冶 | 04 | 女 | 1980-7-30 | 2000-9-1 | 599 | TRUE |
199934202152 | 王涛 | 42 | 男 | 1980-1-2 | 1999-9-1 | 576 | TRUE |
199934101067 | 高磊 | 41 | 男 | 1980-5-3 | 1999-9-1 | 543 | FALSE |
2.教师基本表
表名:教师
结构:
字段名 | 类型 | 宽度 | 小数位数 | 索引 |
教师编号 | 字符型 | 4 |
| 主索引 |
教师姓名 | 字符型 | 8 |
|
|
性别 | 字符型 | 2 |
|
|
职称 | 字符型 | 8 |
|
|
通讯地址 | 字符型 | 40 |
|
|
邮政编码 | 字符型 | 6 |
|
|
电话 | 字符型 | 20 |
|
|
电子信箱 | 字符型 | 40 |
|
|
记录:
教师编号 | 教师姓名 | 性别 | 职称 | 通讯地址 | 邮政编码 | 电话 | 电子信箱 |
CC01 | 陈利民 | 男 | 教授 | 武汉大学182栋8号 | 430072 | 027-87675423 | lmchen@263.net |
CC02 | 王惠敏 | 女 | 副教授 | 武汉市武昌区民主路2345号 | 430043 | 027-87876745 | hmwang@163.net |
CC03 | 刘江 | 男 | 讲师 | 武汉大学11栋12号 | 430072 |
|
|
CS01 | 张健中 | 男 | 副教授 | 武汉市中山大道345号 | 430030 | 027-83457231 | jzzhang@263.net |
CS02 | 吴秀芝 | 女 | 讲师 | 武汉大学14栋8号 | 430072 | 027-87883476 | xzwu@263.net |
3.课程基本表
表名:课程
结构:
字段名 | 类型 | 宽度 | 小数位数 | 索引 |
课程编号 | 字符型 | 4 |
| 主索引 |
课程名称 | 字符型 | 20 |
|
|
学时 | 数值型 | 3 | 0 |
|
学分 | 数值型 | 2 | 0 |
|
课程性质 | 字符型 | 8 |
|
|
备注 | 备注型 |
|
|
|
记录:
课程编号 | 课程名称 | 学时 | 学分 | 课程性质 |
CC01 | C语言程序设计 | 48 | 3 | 选修课 |
CC02 | FoxPro数据库及程序设 | 32 | 2 | 选修课 |
CC03 | 多媒体计算机技术 | 32 | 2 | 选修课 |
CS01 | 计算机原理 | 48 | 3 | 必修课 |
CS02 | 编译原理 | 48 | 3 | 指定选修 |
4.学生选课表
表名:学生选课
结构:
字段名 | 类型 | 宽度 | 小数位数 | 索引 |
学号 | 字符型 | 12 |
| 普通索引 |
课程编号 | 字符型 | 4 |
| 普通索引 |
开课时间 | 日期型 |
|
| 普通索引 |
成绩 | 数值型 | 3 | 0 | 普通索引 |
记录:
学号 | 课程编号 | 开课时间 | 成绩 |
200010301001 | CC01 | 2001-2-20 | 0 |
200010301001 | CC03 | 2001-2-20 | 0 |
200010301001 | CS01 | 2001-9-1 | 0 |
200010301020 | CC02 | 2001-2-20 | 0 |
200010301020 | CS03 | 2001-2-20 | 0 |
200020302045 | CC02 | 2001-2-20 | 0 |
200034201002 | CC03 | 2001-2-20 | 0 |
200034202123 | CS02 | 2001-9-1 | 0 |
199920403128 | CC01 | 2000-2-23 | 86 |
199924104112 | CS02 | 2000-2-23 | 50 |
199924104112 | CS02 | 2001-2-20 | 0 |
199934202152 | CC02 | 2000-2-23 | 91 |
199934202152 | CC03 | 2000-2-23 | 85 |
199934202152 | CS01 | 2000-9-3 | 78 |
199934202152 | CS02 | 2000-9-3 | 75 |
200010401081 | CC02 | 2001-2-20 | 0 |
|
|
|
|
5.教师任课表
表名:教师任课表
结构:
字段名 | 类型 | 宽度 | 小数位数 | 索引 |
课程编号 | 字符型 | 4 |
| 普通索引 |
教师编号 | 字符型 | 8 |
| 普通索引 |
记录:
课程编号 | 教师编号 |
CC01 | CC01 |
CC01 | CC02 |
CC02 | CC01 |
CC02 | CC03 |
CC03 | CC02 |
CC03 | CC03 |
CS01 | CS01 |
CS01 | CS02 |
CS02 | CS01 |
6.专业表
表名:专业表
结构:
字段名 | 类型 | 宽度 | 小数位数 | 索引 |
专业编号 | 字符型 | 4 |
| 主索引 |
专业名称 | 字符型 | 40 |
|
|
所属系 | 字符型 | 40 |
|
|
备注 | 备注型 |
|
|
|
记录:
专业编号 | 专业名称 | 所属系 |
03 | 水动 | 水利 |
04 | 农田 | 水利 |
05 | 水资源 | 水利 |
41 | 自动化 | 电力 |
42 | 热动 | 电力 |
Ø 应用程序设计
(一)程序总体结构设计
在开始程序设计前,应先将程序的总体结构以层次图的形式表示出来,便于对程序分层编程和实现。如图3所示。
图的第一层为系统层,通常对应主程序;第二层为子系统层,一般起划分系统功能的作用,通常对应主菜单;第三层为功能层,对应菜单项,一般通过表单的调用实现某些特定的功能。
(二)界面设计
1.封面设计(封面.scx)
选中项目管理器中文档-表单,按下“新建”按钮,在随后打开的对话框中单击“新建表单”按钮,弹出表单设计器和一个表单,其对象名为Form1。在表单中添加一个Lable对象,采用系统默认名称Label1,一个Timer对象,系统默认名称Timer1,如图4所示。设置对象属性如下:
图4“封面”表单
(1)Form1的属性设置及事件代码
属性名 | 设置值 | 说明 |
Left | 0 |
|
Top | 0 |
|
Heigh | 431 |
|
Width | 771 |
|
BorderStyle | 0-无边框 |
|
Picture | C:¥windows¥circles.bmp | 设置窗口背景 |
TitleBar | 0-关闭 | 只显示背景和标签 |
Window State | 2-最大化 |
|
Activate事件代码: && 调整标签在启动窗口中的位置
thisform.label1.top=thisform.height/3
thisform.label1.left=(thisform.width-thisform.label1.width)/2
thisform.label1.visible=.t.
RightClick事件代码:
thisform.release &&关闭启动窗口
(2)Label1的属性设置
属性名 | 设置值 | 说明 |
Top | 132 |
|
Left | 60 |
|
Height | 60 |
|
Width | 517 |
|
Caption | 学生选课管理系统 |
|
FontName | 隶书 |
|
FontSize | 48 |
|
ForeColor | 255,128,128 |
|
BackStyle | 2-透明 | 以免遮住窗口背景 |
Visible | F.-假 | 以免在调整标签位置时闪动 |
(3)Timer1的属性设置及事件代码
属性名 | 设置值 | 说明 |
Interval | 5000 | 每5000ms调用一次Timer事件 |
Timer事件代码:
thisform.release
2.主菜单设计(主菜单.mnx)
选中项目设计器中其他-菜单,单击“新建”按钮,在弹出的对话框中选择“菜单”按钮,参照总体结构图,设计主菜单如下。
基本信息 | 选课信息 | 统计查询 | 报表打印 | 代码维护 |
学生名册 (学生基本情况.scx) | 选课登记 (选课登记.scx) | 按课程查询 (按课程查询.scx) | 学生成绩单 | 课程代码 |
教师名册 (教师.scx) |
| 按学生查询
| 教师工作量 |
|
课程信息 (课程信息.scx) |
| 按课程平均 (按课程求平均.scx) | 课程成绩单 | |
退出 (命令) | 按学生平均 |
|
“退出”菜单项命令如下:
clear events && 退出事件循环
从菜单文件生成菜单程序“主菜单.mpr”
3.“学生名册”表单(学生基本情况.scx)
学生名册表单用于输入、修改、删除、查询学生信息。窗口设计见图5。在窗口上单击鼠标右键打开弹出菜单,选择数据环境打开“数据环境设计器“,在数据环境中添加“学生”、“专业表”两个表,建立关联。如图6所示。
(1)StudentForm的属性设置
属性名 | 设置值 | 说明 |
Name | StudentForm |
|
Caption | 学生基本情况 |
|
AutoCenter | .T.-真 | 窗口自动居中 |
BorderStyle | 2-固定对话框 | 无需用户调整窗口大小 |
MaxButton | .F.-假 | 同上 |
图5 “学生基本情况“表单
图6“学生基本情况”表单的数据环境设置
(2)标签和文字框的设置
从数据环境将下列字段拖到表单中规定的位置,产生相应的标签和文本框:学生表中的学号、姓名、出生日期、入学时间、入学成绩、简历等字段;专业表中的专业编号、专业名称、所属系等字段。从数据环境来产生标签和文本框,不仅速度快,而且标签的Caption和Name属性、文本框的Name属性都会自动设定位与源字段有关的名字,文本框也会自动与源表中的源字段绑定。
(3)“专业编号”列表框的设置及事件代码
从表单控件工具栏中选择“组合框”工具,在窗口上相应位置单击,产生一个组合框Combo1,设置其属性。
属性名 | 设置值 | 说明 |
Name | Combo1 |
|
ControlSource | 学生.专业编号 | 数据存储的字段 |
RowSource | 专业表.专业编号 | 列表框中数据来源字段 |
RowSourceType | 6-字段 | 数据来源为字段 |
Style | 2-下拉列表框 |
|
Valid事件代码:
thisform.refresh
(4)“团员”复选框的设置
从数据环境中将“学生.团员否“字段拖到窗口上相应的位置,会自动产生团员复选框。并且将它与学生.团员否字段绑定。
(5)“性别”选项按钮组的设置
从表单控件工具栏中选择选项按钮组工具,在窗口相应的位置单击鼠标左键,创建选项按钮组控件,在控件上单击鼠标右键打开弹出式菜单,选择生成器材单项,打开选项组生成器窗口,如图7所示,按步骤完成如下操作。
图7设置“性别”选项组
第一步,将标题改为“男”、“女”;
第二步,将布局改为水平排列;
第三步,将值与学生.性别字段绑定。单击“确定”完成设置。
(6)命令按钮组设置与事件代码
从表单控件工具栏中选择命令按钮组工具,在窗口相应的位置单击鼠标左键创建命令按钮组控件CommandGroup1,在控件上单击鼠标右键弹出菜单,选择生成器菜单项,打开命令组生成器窗口,格式与图8.14类似。按要求第一步设置按钮数目及每个按钮的标题(见图8.12);第二步设置布局为水平排列,单击“确定”即可生成按钮组。
CommandGroup1的Click事件代码:
do case
case this.value=1 && 到首页
go top
case this.value=2 && 到上页
if not bof()
skip -1
endif
case this.value=3 && 到下页
skip
if eof()
skip -1
endif
case this.value=4 && 到末页
go bottom
case this.value=5 && 按学号查询
xh=''
do form 输入学号 && 打开学号输入窗口(见下文),关闭时
&& 将输入的学号返回
dqjlh=recno()
if len(xh)<>0
locate for 学号=xh
if not found()
wait window '无此学号!'
go dqjlh
endif
endif
case this.value=6 && 新增学生名单
zy=messagebox('需要增加学生名单吗?',4+32+256,'确认')
if zy=6 && 对话框含“是”“否”按钮,按下“是”按钮返回6
append blank
endif
case this.value=7 && 删除当前学生名单
sy=messagebox('需要删除当前的学生名单吗?',4+32+256,'确认')
if sy=6
delete
pack
endif
case this.value=8 && 关闭当前窗口
thisform.release
endcase
thisform.refresh
4.“输入学号”表单(输入学号.scx)
在“学生名册”窗口中,当单击寻页按钮时,调用“输入学号”表单,通过公共变量xh,将输入的需要查询的学号传回到“学生名册”窗口,并进行定位,如果没有相应学号的数据,则在等待窗口中显示“无此学号”。“输入学号”窗口如图8所示。
图8 “输入学号”表单窗口
(1)Form的属性设置
属性名 | 设置值 | 说明 |
AutoCenter | .T.-真 |
|
BorderStyle | 2-固定对话框 |
|
Caption | 输入学号 |
|
ControlBox | .F.-假 |
|
Name | noForm |
|
WindowStyle | 1-模式 | 在窗口关闭前不能操作其他窗口 |
(2)命令按钮组的属性设置及事件代码
利用生成器,创建命令按钮组CommandGroup1其中包含“确定”、“取消”两个按钮。
CommandGroup1的Click事件代码:
do case
case this.value=1 &&单击“确定”,将文本框中的值赋予全局变量xh
xh=trim(thisform.text1.value)
thisform.release
case this.value=2 &&单击“取消”,将全局变量xh赋空字符串
xh=''
thisform.release
endcase
5.“选课登记”表单(选课登记.scx)
“选课登记”表单用于输入、修改和查询学生选课信息,需要使用学生选课表、学生表和课程表三个表。在“选课登记”表单的数据环境中加入这三个表,同时以建立学生选课表为主表建立学生选课表和学生表、学生选课表和课程表之间的关联,如图9所示。
图9 “选课登记”表单的数据环境
和“学生名册”表单类似,从数据环境中将需要的数据拖到表单窗口的相应位置,创建“选课登记”表单如图10所示。
图10 “选课登记”表单
窗口属性的设置和“学生名册”表单类似,其中命令组可以从“学生名册”表单中复制过来,修改其Click事件中的代码如下:
do case
case this.value=1
go top
case this.value=2
if not bof()
skip -1
endif
case this.value=3
skip
if eof()
skip -1
endif
case this.value=4
go bottom
case this.value=5
kcbh=''
do form 输入学号
dqjlh=recno()
if len(kcbh)<>0
locate for 课程编号=kcbh
if not found()
wait window '无此选课记录!'
go dqjlh
endif
endif
case this.value=6
zy=messagebox('需要增加选课记录吗?',4+32+256,'确认')
if zy=6
append blank
endif
case this.value=7
sy=messagebox('需要删除当前的选课记录吗?',4+32+256,'确认')
if sy=6
delete
pack
endif
case this.value=8
thisform.release
endcase
thisform.refresh
“课程编号”列表框属性的设置参照“学生名册”表单。
6.“按课程查询”表单(按课程查询.scx)
该表单可以按所选定的课程查询出选修了该课程的所有学生名单、开课时间以及成绩,数据涉及到学生选课和课程,将这两个表加入到数据环境中,窗口格式的建立如图11所示。
图11 “按课程查询”表单
(3)关闭命令按钮的Click时间代码
thisform.release
7.“按课程统计”表单(按课程统计.scx)
“按课程统计”表单提供用户按课程统计没门课程的平均成绩,为了使表单界面设计简单,可以先建立一视图,将成绩按课程分组求平均值,视图的建立可利用VFP提供的视图设计器,将学生选课表和课程表加入视图设计器中,将学生选课.课程编号、课程.课程名称从可选字段列表加入到选定字段列表框中,利用表达式生成器生成AVG(学生选课.成绩),并将它加入到选定字段列表框中。如图12所示。
图12视图设计器
设置连接条件为:学生选课.课程编号=课程.课程编号
筛选条件为:NOT 学生选课.成绩=0
排序依据为:学生选课.课程编号
分组依据为:学生选课.课程编号
视图名为: v学生选课_课程_统计1
最后将新建的视图加到表单的数据环境中,表单窗口的设计如图13所示。
图13 “按课程平均”表单
成绩列表框仍然利用列表框生成器设计。