学生管理系统结构讲解
复合布局集成
表格数据显示
系统介绍
本节课我们会通过一个学生管理系统来学习
其中
,
分为两个角色
老师
Teacher
学生
Student
在该系统中
,
主要完成老师管理学生的功能
,
在这节课中
,
主要完成以下操作
public class
Teacher
{
private
Integer
id
;
private
String
name
;
private
String
password
;
private
String
gender
;
}
public class
Student
{
private
Integer
id
;
private
String
name
;
private
String
password
;
private
String
gender
;
private
String
address
;
private
String
hobby
;
}
登录页面搭建
新建
MyLogin.java
,
完成登录界面排版
完整代码
@Override
public
void
start
(
Stage primaryStage
)
throws
Exception
{
//
新建布局
GridPane gridPane
=
new
GridPane
();
//
设置居中方式
gridPane
.
setAlignment
(
Pos
.
CENTER
);
//
调整间隙
gridPane
.
setHgap
(
10
);
gridPane
.
setVgap
(
10
);
//
新建文本标签:用户名
Label l1
=
new
Label
(
"
老师名称
"
);
//
新建输入框
登录按钮的事件设置
使用
setOnAction
完成事件设置
完成数据取值操作
实现数据库验证逻辑
TextField name
=
new
TextField
();
//
新建文本标签:用户密码
Label l2
=
new
Label
(
"
老师密码
"
);
//
新建密码框
PasswordField pwd
=
new
PasswordField
();
//
登录按钮的创建
Button login
=
new
Button
(
"
登录
"
);
//
前往注册按钮的创建
Button goRegister
=
new
Button
(
"
前往注册
"
);
//
添加控件进行位置绑定
gridPane
.
add
(
l1
,
0
,
0
);
gridPane
.
add
(
name
,
1
,
0
);
gridPane
.
add
(
l2
,
0
,
1
);
gridPane
.
add
(
pwd
,
1
,
1
);
gridPane
.
add
(
login
,
0
,
2
);
gridPane
.
add
(
goRegister
,
1
,
2
);
//
生成场景并完成布局绑定
,
同时设定场景大小
Scene scene
=
new
Scene
(
gridPane
,
300
,
200
);
//
主容器标题设置
primaryStage
.
setTitle
(
"
登录页面
"
);
//
给主容器绑定场景(让场景显示出来)
primaryStage
.
setScene
(
scene
);
//
不要忘了这一行
,
让主容器显示
primaryStage
.
show
();
}
login
.
setOnAction
(
a
->
{
})
String
username
=
name
.
getText
();
String
password
=
pwd
.
getText
();
//
此处是模拟实现
if
(
"root"
.
equals
(
username
)
&&
"root123"
.
equals
(
password
)) {
}
else
{
}
Alert
进阶
之前我们讲过了
Alert
的基本使用
,
现在可以进行进阶操作了
👨🏭
通过分析
Alert
的构造函数:
第一个参数
,
弹框的类型
,
第一次课程中有分析
,
主要是图标的不同
第二个参数
,
弹框的提示信息
第三个参数
,
一个按钮可变数组
,
用于弹框下方显示的按钮
可以可以通过给构造函数中传入多个按钮来自定义弹框
public Alert(Alert.AlertType,String,ButtonType...) {
public static enum
AlertType
{
NONE
,
INFORMATION
,
WARNING
,
CONFIRMATION
,
ERROR
;
}
public static final
ButtonType APPLY
;
public static final
ButtonType OK
;
public static final
ButtonType CANCEL
;
public static final
ButtonType CLOSE
;
public static final
ButtonType YES
;
public static final
ButtonType NO
;
public static final
ButtonType FINISH
;
public static final
ButtonType NEXT
;
public static final
ButtonType PREVIOUS
;
Alert alert
=
new
Alert
(
Alert
.
AlertType
.
ERROR
,
"
登录失败
,
请重
试
"
,
ButtonType
.
OK
,
ButtonType
.
NO
,
ButtonType
.
CLOSE
);
当调用了弹框的
showAndWait()
方法后
,
我们会接收到弹框被调用的按钮,
我们只要做判断
,
就可以知道选择的按钮了
,
然后在执行相关的操作
注册页面搭建
使用网格布局搭建页面
完整代码
Optional
<
ButtonType
>
type
=
alert
.
showAndWait
();
if
(
type
.
get
()
==
ButtonType
.
OK
){
}
if
(
type
.
get
()
==
ButtonType
.
NO
){
}
if
(
type
.
get
()
==
ButtonType
.
CLOSE
){
}
@Override
public
void
start
(
Stage primaryStage
)
throws
IOException
{
//
新建布局
GridPane gridPane
=
new
GridPane
();
//
设置居中方式
gridPane
.
setAlignment
(
Pos
.
CENTER
);
//
调整间隙
gridPane
.
setHgap
(
20
);
gridPane
.
setVgap
(
20
);
//
文本标签
Label l1
=
new
Label
(
"
老师名称
"
);
Label l2
=
new
Label
(
"
老师密码
"
);
切换与新开
现在我们需要给
前往登录
按钮设置点击事件
,
目的是点击它能够打开注册界面
,
所以我们需要了解如何进行页面新开与跳转
场景切换
根据之前的介绍
,FX
的构成部分分为
Stage
舞台
Label l3
=
new
Label
(
"
老师性别
"
);
//
输入框
TextField f1
=
new
TextField
();
PasswordField f2
=
new
PasswordField
();
//
性别
ToggleGroup group
=
new
ToggleGroup
();
RadioButton men
=
new
RadioButton
(
"
🚹
"
);
RadioButton miss
=
new
RadioButton
(
"
🚺
"
);
men
.
setToggleGroup
(
group
);
miss
.
setToggleGroup
(
group
);
men
.
setSelected
(
true
);
HBox h1
=
new
HBox
();
h1
.
getChildren
().
addAll
(
men
,
miss
);
//
登录按钮的创建
Button register
=
new
Button
(
"
注册
"
);
Button cancel
=
new
Button
(
"
取消
"
);
//
用户名
gridPane
.
add
(
l1
,
0
,
0
);
gridPane
.
add
(
f1
,
1
,
0
);
//
用户密码
gridPane
.
add
(
l2
,
0
,
1
);
gridPane
.
add
(
f2
,
1
,
1
);
//
用户性别
gridPane
.
add
(
l3
,
0
,
2
);
gridPane
.
add
(
h1
,
1
,
2
);
//
按钮
gridPane
.
add
(
register
,
0
,
3
);
gridPane
.
add
(
cancel
,
1
,
3
);
//
生成场景并完成布局绑定
,
同时设定场景大小
Scene scene
=
new
Scene
(
gridPane
,
400
,
300
);
//
主容器标题设置
primaryStage
.
setTitle
(
"
网格登录
"
);
//
给主容器绑定场景(让场景显示出来)
primaryStage
.
setScene
(
scene
);
//
不要忘了这一行
,
让主容器显示
primaryStage
.
show
();
}
Scene
场景
,
可以理解为舞台上的节目
,
一个舞台可以呈现多个节目
,
对于场景的切换
,
就是将舞台的场景进行重新设置
setScene(Scene)
就可以完成了
我们可以通过代码来实践:
构建两个场景
,
分别放置不同的内容
FlowPane flow01=new FlowPane();
Label l1 = new Label("
我是场景一
");
flow01.getChildren().add(l1);
Scene s1 = new Scene(flow01);
FlowPane flow02=new FlowPane();
Label l2 = new Label("
我是场景二
");
flow02.getChildren().add(l2);
Scene s2 = new Scene(flow02);
给场景一放置一个按钮控件
,
当我们点击按钮的时候
,
将舞台场景切换为场景二
Button btn
=
new
Button
(
"
切换场景二
"
);
btn
.
setOnAction
(
a
->
{
primaryStage
.
setScene
(
s2
);
});
flow01
.
getChildren
().
add
(
btn
);
设置场景一为默认显示
primaryStage
.
setScene
(
s1
);
默认视图:
点击按钮后:
完整代码
新开窗口
进行到这里
,
同学们应该对于这个
Stage
和
Scene
大概明白的差不多了
一个
Stage
就是一个窗口
,
Scene
就是该窗口中显示的内容
,
如果需要新开一个窗口
,
那就意味存在多个舞台
Stage
完成功能:点击按钮新开注册页面
删除注册页面的
main
方法或者是里面的
launch()
方法
,
因为该方法是
JavaFX
程序的入口
,
项目必须有且只需要一个
@Override
public
void
start
(
Stage primaryStage
)
throws
Exception
{
FlowPane flow01
=
new
FlowPane
();
Label l1
=
new
Label
(
"
我是场景一
"
);
flow01
.
getChildren
().
add
(
l1
);
Scene s1
=
new
Scene
(
flow01
);
FlowPane flow02
=
new
FlowPane
();
Label l2
=
new
Label
(
"
我是场景二
"
);
flow02
.
getChildren
().
add
(
l2
);
Scene s2
=
new
Scene
(
flow02
);
Button btn
=
new
Button
(
"
切换场景二
"
);
btn
.
setOnAction
(
a
->
{
primaryStage
.
setScene
(
s2
);
});
flow01
.
getChildren
().
add
(
btn
);
primaryStage
.
setScene
(
s1
);
primaryStage
.
show
();
}
public class
MyRegister
extends
Application
{
@Override
public
void
start
(
Stage primaryStage
)
throws
IOException
{
//
此处省略了页面搭建代码
}
}
编写登录页面
前往注册
点击事件
goRegister
.
setOnAction
(
a
->
{
try
{
//
在该处实例化注册页面并调用
start
方法
//
该方法需要一个
Stage
舞台对象 我们可以直接实例化一个给他
//
也可以直接把
primaryStage
给它
new
MyRegister
().
start
(
new
Stage
());
}
catch
(
Exception e
) {
e
.
printStackTrace
();
}
});
此处会出来两个界面
,
如果需要关闭登录界面
,
可以调用 对应舞台的
close()
方法
primaryStage
.
close
();
完整代码
//
前往注册按钮的创建
Button goRegister
=
new
Button
(
"
前往注册
"
);
goRegister
.
setOnAction
(
a
->
{
try
{
new
MyRegister
().
start
(
new
Stage
());
primaryStage
.
close
();
}
catch
(
Exception e
) {
e
.
printStackTrace
();
}
});
首页搭建
布局分析
结构对比
所以搭建整体布局为
BorderPane borderPane
=
new
BorderPane
();
顶部
需要放入多个控件
,
且位于一行
,
可以选择
FlowPane
或者
HBOX
底部
与顶部类似
中部
这个部位是表格控件
TableView
//
顶部
FlowPane topPane
=
new
FlowPane
();
Label l1
=
new
Label
(
"
学生名称
"
);
TextField f1
=
new
TextField
();
Button b1
=
new
Button
(
"
查询
"
);
topPane
.
getChildren
().
addAll
(
l1
,
f1
,
b1
);
topPane
.
setHgap
(
10
);
//
这里是为了调整控件左右的间隙
topPane
.
setPadding
(
new
Insets
(
10
));
//
这里是为了调整布局上下的间隙 防止太过紧密
borderPane
.
setTop
(
topPane
);
//
底部
FlowPane bottomPane
=
new
FlowPane
();
Button g1
=
new
Button
(
"
增加
"
);
Button g2
=
new
Button
(
"
删除
"
);
Button g3
=
new
Button
(
"
修改
"
);
Button g4
=
new
Button
(
"
退出
"
);
bottomPane
.
getChildren
().
addAll
(
g1
,
g2
,
g3
,
g4
);
bottomPane
.
setHgap
(
10
);
bottomPane
.
setPadding
(
new
Insets
(
10
));
borderPane
.
setBottom
(
bottomPane
);
TableView tableView = new TableView();
borderPane.setCenter(tableView);
我们需要为表格设置列
TableColumn
将列绑定到表格控件中
表格控件
列值处理器
表格控件的数据可以来源于
List
集合
,
所以我们可以选择从数据库查询出来的学生
Student
对象集合
我们从
Dao
层拿到学生集合之后
,
需要将该集合中的数据绑定到表格控件中
,
所以我们需要给该控件的列进行代码设置
TableColumn c1
=
new
TableColumn
(
"
学生编号
"
);
TableColumn c2
=
new
TableColumn
(
"
学生名字
"
);
TableColumn c3
=
new
TableColumn
(
"
学生密码
"
);
TableColumn c4
=
new
TableColumn
(
"
学生性别
"
);
TableColumn c5
=
new
TableColumn
(
"
学生地址
"
);
TableColumn c6
=
new
TableColumn
(
"
学生爱好
"
);
tableView
.
getColumns
().
addAll
(
c1
,
c2
,
c3
,
c4
,
c5
,
c6
);
//StudentDao
public List<Student> list(){
//
此处省略代码
}
其中
,
new PropertyValueFactory(xx)
这行代码会自动帮助我们从学生对象中取值对应的属性
,
我们只需要改变列的名称与对
应的属性值
xx
即可完成数据显示
数据绑定
需要注意的点
:
绑定数据的方式
未指定泛型时候
,
必须使用
FXCollections.observableList(list)
对普通的
List
进行转换才能被表格所识别
指定了泛型后
,
可以直接使用
addAll()
方法合并集合
完整代码
//c1:
学生编号
->
对应
Student
对象的
id
属性
c1
.
setCellValueFactory
(
new
PropertyValueFactory
(
"id"
));
//c1:
学生名字
->
对应
Student
对象的
username
属性
c2
.
setCellValueFactory
(
new
PropertyValueFactory
(
"name"
));
//c1:
学生密码
->
对应
Student
对象的
password
属性
c3
.
setCellValueFactory
(
new
PropertyValueFactory
(
"password"
));
//c1:
学生性别
->
对应
Student
对象的
gender
属性
c4
.
setCellValueFactory
(
new
PropertyValueFactory
(
"gender"
));
//c1:
学生地址
->
对应
Student
对象的
address
属性
c5
.
setCellValueFactory
(
new
PropertyValueFactory
(
"address"
));
//c1:
学生爱好
->
对应
Student
对象的
hobby
属性
c6
.
setCellValueFactory
(
new
PropertyValueFactory
(
"hobby"
));
//
此处为模拟数据
,
模拟数据库查询出来的
List<Student>
集合
List
<
Student
>
list
=
new
ArrayList
<>
() {
{
add
(
new
Student
(
2
,
"
小明
"
,
"1234"
,
"
女
"
,
"
湖南省
"
,
"
打篮球
"
));
add
(
new
Student
(
3
,
"
小李
"
,
"1234"
,
"
女
"
,
"
湖南省
"
,
"
打篮球
"
));
add
(
new
Student
(
4
,
"
小虎
"
,
"1234"
,
"
女
"
,
"
湖南省
"
,
"
打篮球
"
));
add
(
new
Student
(
5
,
"
小鹿
"
,
"1234"
,
"
女
"
,
"
湖南省
"
,
"
打篮球
"
));
add
(
new
Student
(
6
,
"
小黑
"
,
"1234"
,
"
女
"
,
"
湖南省
"
,
"
打篮球
"
));
}