eclipse+MySQL5.5+navicat,画界面:javafx_scenebuilder
两个主程序:AdminEntry.java和UserEntry.java。运行普通用户时,需要运行UserEntry.java,管理员角色登录时,需要运行AdminEntry.java。
用户登录:分为登录和注册两个模块。登录时,输入手机号和密码,点击登录。
注册:
未检测状态:
管理员登录界面:
管理员登录成功:
管理员更新用户信息
正常:绿色二维码;密接:黄色二维码;
确诊:红色二维码;未检测:黑色二维码;
JavaFX是一个由Java 编写的类和接口的Java库。JavaFX提供一系列的图形、媒体包,使开发者可以依此设计、创建、测试、调试和部署丰富的客户端跨平台应用程序。
JavaFX库是由Java API编写,JavaFX 应用程序可以调用任意的Java库。
JavaFX应用程序的外观和样式可以定制。叠层样式表(CSS)将代码和外观进行分离,让我们可以专注于自己的逻辑代码,可以更加容易的定制应用程序的外观。将UI写进FXML脚本。不通过代码创建界面,使用JavaFX 提供的Scene Builder 创建界面。
FXML是一种基于XML的声明性标记语言,用于构建JavaFX应用程序的用户接口。**可以在FXML文件里面写相关代码或者用JavaFX Scene Builder工具交互设计图形用户接口。**JavaFX Scene Builder生成的FXML标记可以轻松的移植到开发者编写逻辑代码的IDE中。
WebView使JavaFX应用程序拥有内嵌网页的能力。
内建UI控件和CSS
画布API:该API可以使用户在JavaFX 的scene中的一块图形节点(node)区域直接进行绘制图形
多点触控支持、高性能的媒体引擎等等
通过JavaFX你可以构建多种应用程序。
页面布局:
界面的设置:javafx_scenebuilder
界面控件:Tab,AnchorPane、VBox(纵向排布)、HBox(水平排布),TextField
通过Layout x,Layou y来调整控件的位置(左上角的坐标点)
实现登录功能,首先要获取界面中输入的数据
**在MVC中,通过视图View和用户交互,在交互过程中可以获得数据,数据的流向由控制器Controller进行管理,一般来讲,只要有视图,就要有对应的控制器。**控制器需要自己动手做。UserIndexController,在javafx中,视图对应的控制器类必须在同一个包里面。
注解@FXML:让注解标注的变量(控制器里的属性)将来能够跟视图上的控件捆绑在一起,让两者建立关联
注解@FXML的编写,方便和视图捆绑在一起
public class UserIndexController{
@FXML
private TextField txtmobile;//登录的手机号
@FXML
private PasswordField txtpwd;//登录的密码框
@FXML
private TextField txtremobile;//注册的手机号
@FXML
private PasswordField txtregpwd;//注册的密码
@FXML
private TextField txtuname;//注册的真实姓名
@FXML
private TextField txtcheck;//验证码/
@FXML
private TextField txtid;//身份证号
}
导包快捷键:ctrl+shift+o
将注解的这些属性和控件进行绑定
运行UserIndex.fxml,进入scenebuilder
在scenebuilder左下方找到Controller,找到Controller Class,右边小齿轮,关联
选择控件,右边找Code,找到fx:id,下来列表,进行捆绑
一个一个的完成绑定任务
运行UserIndex.fxml,进入scenebuilder
此时,绑定工作到此结束
如何实现登录功能呢:在控制器类里面声明相应的方法,然后让方法和按钮(登录按钮)关联在一起
接上
@FXML
private void login(){
//要获取登录文本框和密码框里面的值,getText()方法
//在类的方法中访问类的属性
}
要获取登录文本框和密码框里面的值,getText()方法,例如:txtmobile.getText()
String mobile=txtmobile.getText();
String pwd=txtpwd.getText();
然后,让方法与登录按钮关联起来:在scenebulider中,选中登录控件,在右侧Code中,找到On Mouse Clicked,此时下面会自动出现刚刚写的login方法
保存
在main方法中获取控制器,使用getController()方法
...
FXMLLoader loader=new FXMLLoader();
...
//loader获取布局器
BorderPane bp=loader.load();
...
//loader获取控制器
UserIndexController userIndexController=loader.getController();
运行,此时可以实现获取输入的数据
同理,可以写一个注册的方法
==》UserIndexController.java
// 实现用户注册的方法
@FXML
private void reg(){
User regUser=new User();
// 接收注册界面的身份证号数据
regUser.setId(txtid.getText());
// 接收注册界面的手机号
regUser.setMobile(txtregmobile.getText());
// 接收密码
regUser.setPwd(txtregpwd.getText());
// 接收真实姓名
regUser.setUname(txtuname.getText());
// 验证内容
if(txtregmobile.getText().length()==0){
AlertController.showAlert("注册提示", "手机号不能为空", "请填写手机号");
return;
}
if(txtregpwd.getText().length()==0){
AlertController.showAlert("注册提示", "密码号不能为空", "请填写注册密码");
return;
}
if(txtid.getText().length()==0){
AlertController.showAlert("注册提示", "身份号不能为空", "请填写身份证号");
return;
}
if(txtuname.getText().length()==0){
AlertController.showAlert("注册提示", "名字不能为空", "请填写名字");
return;
}
// 调用Dao层,将注册输入插入数据库
int row=ud.reg(regUser);
if(row>0){
AlertController.showAlert("注册提示", "注册成功", "可以接下来登录了");
}else{
AlertController.showAlert("注册提示", "注册失败", "请检查注册数据");
}
// 注册无论成败,都应该清空注册界面的数据
txtid.setText("");
txtregmobile.setText("");
txtregpwd.setText("");
txtuname.setText("");
}
要完成注册功能,前端接受数据,数据进入数据表,所以数据库里要有数据表,navicat工具
密码:root ,用户名:root
新建数据库,mypass数据库名。新建表myuser(本项目比较简单,就两张表),
前端有视图,底层有数据库,还需要在中间有跟数据库对应的实体类,也就是MVC中的Model数据模型:与数据表对应的实体业务类
实体类:User.java,包括各种属性,以及属性的读取器和设置器(get set)
JDBC基本操作:
将mysql-connector-java-bin.jar包粘贴到lib文件夹里,再加到项目当中,选择Add to Build Path,加到编译路径里面
这样,这个JDBC的jar包就进到整个程序里面了,项目文件夹里多了Referenced Libraries
加载JDBC程序的过程:
===》TestJDBC.java(测试类)
1、需要用反射机制,来加载驱动程序的字节码
Class.forName("com.mysql.jdbc.Driver");
//大写的Class,代表字节码
2、建立数据库连接
用一个重要的类:DriverManager,有个方法getConnection(测试类)
String url="jdbc:mysql://localhost:3306/mypass";//5.5版本,如果是8版本,要在后面再加上时区
String uid="root";
String pwd="root";
//返回一个数据库连接对象
Connection con=DriverManager.getConnection(url,uid ,pwd);//数据库的连接路径,用户名,密码
3、进行SQL操作
查询操作:
√
String sql="select * from myuser";//查询
//将SQL语句传导给相应的执行对象,prepareStatement是一个SQL的执行对象,即SQL语句封装在这个对象中了,让他进行查询操作
PreparedStatement ps=con.prepareStatement(sql);
//执行查询
ResultSet rs=ps.executeQuery();//用executeQuery()进行查询,返回一个结果集
**得到结果集之后,需要把里面的数据取出来。**可以使用while循环,先判断里面有没有数据,get方法
√
//建立一个和用户User有关的集合
List<User> ulist=new ArrayList<User>();//创建集合,将来查询到的结果放到List当中,有了List才能呈现到界面上
//集合和数组最大的差别:数组定长,集合没有元素限制。数组当中既可以放对象又可以放基本数据类型,但是List当中不能放基本数据类型
while(rs.next()){//如果结果集不为空,next()方法运行的结果就是真值
String mobile=rs.getString("mobile");//手机号在数据库中是varchar变长数据类型,所以要用getString,括号里面跟上变量的名称。此时可以将手机号取出来
String uname=rs.getString("uname");//将真实姓名取出来
String id=rs.getString("id");//手机号取出来
String health=rs.getString("health");//取出健康状况
Date regDate=rs.getDate("regdate");//取出注册日期
//取出来的这些数据要用到我的用户对象里面
//建立一个用户类型的对象
User u=new User();
//将数据库刚刚取出来的结果集的值,填充到User对象里
u.setHealth(health);
u.setId(id);
u.setMobile(mobile);
u.setRegdate(regDate);
u.setUname(uname);
//管理员想看所有用户的数据,就得得到一个集合,所以,还要把这些有数据的对象放到集合里面
//把User对象添加到集合里
ulist.add(u);
}
//用增强型的for循环,将集合中的信息遍历输出
for(User user:ulist){//集合里面的对象:集合
System.out.println("姓名:"+user.getUname());//属性读取器,getUname()
System.out.println("身份证号:"+user.getId());
System.out.println("手机号:"+user.getMobile());
}
总结:将数据库中的信息添加到对象中,再把对象的数据添加到集合中,才可以呈现出来
JDBC需要关闭资源
...
if(rs!=null)
rs.close();//关闭结果集
...
if(ps!=null)
ps.close();//关闭PreparedStatement对象
...
if(con!=null)
con.close();//关闭连接对象
//都在try catch finally中
迄今为止:查询写完:TestJDBC.java
建立util包,封装查询操作里面所涉及的一些公共的操作,比如加载驱动,建立连接,关闭资源这些东西
建立DBTool.java(专门来处理数据库的)
public class DBTool{
//1、加载驱动程序
static{//静态块,加载DBTool.java,就会调动静态块运行,就可以调动驱动程序,这样在内存中就会产生一个驱动程序对象,应用程序不停,对象一直在内存中,只要访问到服务器,就可以大家共用这个驱动程序对象
try {
System.out.println("工具类的静态运行");
Class.forName("com.mysql.jdbc.Driver");//用反射机制,来加载驱动程序的字节码
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//2、数据库连接对象
//设置一个方法,可以得到数据库连接对象
public static Connection getConnection(){
String url="jdbc:mysql://localhost:3306/mypas";
String uid="root";
String pwd="root";
Connection con=null;//声明con连接对象
try {
con=DriverManager.getConnection(url,uid ,pwd);//正常运行就可以得到连接对象,如果异常,就保持一个空值的状态
//用DriverManager类里面的getConnection方法,建立数据库连接
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return con;
}
//关闭资源,将连接对象,SQL语句的执行对象,结果集三样东西关闭
public static void close(Connection con,PreparedStatement ps,ResultSet rs){
...
}
}
DAO封装
√
public interface UserDao {
int reg(User user);//注册的方法,将注册的信息封装到一个对象中
User login(String mobile,String pwd);//登录的方法,登录成功后,将信息填到一个对象中,所以这个方法的返回值应该是一个对象,即User
List<User> queryAll();//查询所有人信息的方法,所有的居民需要用集合,所以返回值要用集合类型
int update(User user);//更新特定居民健康信息状态
}
设置一个政府工作人员登录的接口
package com.neuedu.mypass.dao;
public interface AdminDao {
boolean login(String admin,String pwd);//登录成功与否
}
然后做用户的实现类:UserDaoImp.java(implement实现),实现UserDao接口
UserDaoImp.java:
√
封装显示所有用户的方法:
@Override
public List<User> queryAll() {
// TODO Auto-generated method stub
Connection con=DBTool.getConnection();//建立数据库连接
PreparedStatement ps=null;//SQL语句封装在这个对象中了,让他进行查询操作
ResultSet rs=null;//结果集
String sql="select * from myuser";
List<User> ulist=new ArrayList<User>();//声明好集合
try {
ps=con.prepareStatement(sql);//将SQL语句传过来
rs=ps.executeQuery();//执行查询,得到结果集
while(rs.next()){
String mobile=rs.getString("mobile");
String uname=rs.getString("uname");
String id=rs.getString("id");
String health=rs.getString("health");
Date regDate=rs.getDate("regdate");
// 把结果集中每行数据填充一个User对象里
User u=new User();
u.setHealth(health);
u.setId(id);
u.setMobile(mobile);
u.setRegdate(regDate);
u.setUname(uname);
// 把User对象添加到集合里
ulist.add(u);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
DBTool.close(con, ps, rs);//关闭资源,使用封装好的方法
}
return ulist;
}
//基本的查询方法就封装结束了
接下来,封装用户注册的方法:
√
UserDaoImp.java:
@Override
public int reg(User user) {
// TODO Auto-generated method stub
Connection con=DBTool.getConnection();//与数据库建立连接
PreparedStatement ps=null;//sql语句传导的对象
String insert="insert into myuser (mobile,pwd,id,uname,regdate) values (?,?,?,?,?)";//声明语句,?代表通配符
int result=0;
try {
ps=con.prepareStatement(insert);//将insert传进去
ps.setString(1, user.getMobile());//前四个都是字符串,用setString方法,设置值,1表示参数的索引号,第一个是手机号,所以是mobile
ps.setString(2, user.getPwd());//insert语句第二项
ps.setString(3, user.getPwd());//insert语句第三项
ps.setString(4, user.getUname());//insert语句第四项
// util包的Date
Date cur=new Date();
ps.setDate(5, new java.sql.Date(cur.getTime()));//要用sql包里面的date
//getTime()日期对应的毫秒值。取当前日期的毫秒值,再传给sql包里的date
// 执行插入数据操作(执行更新)
result=ps.executeUpdate();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
DBTool.close(con, ps, null);//关闭资源,此时没有结果集,写null
}
return result;
}
封装登录的方法:
UserDaoImp.java:
@Override
public User login(String mobile, String pwd) {
// TODO Auto-generated method stub
Connection con=DBTool.getConnection();
PreparedStatement ps=null;
ResultSet rs=null;
String sql="select * from myuser where mobile=? and pwd=?";//登录方法需要进行验证,所以要加where语句,有一定的条件去判断数据是否存在
User u=null;
try {
ps=con.prepareStatement(sql);//把sql传进去
ps.setString(1, mobile);
ps.setString(2, pwd);
rs=ps.executeQuery();//执行查询,得到结果集
if(rs.next()){
//如果登录成功,可以取出这个对象的所有信息
String id=rs.getString("id");//可以取出身份证号
String uname=rs.getString("uname");//可以取出真实姓名
String health=rs.getString("health");//可以取出健康状态
u=new User();//取出数据之后,需要把数据添加到用户对象u里面
u.setHealth(health);//传数据
u.setId(id);
u.setMobile(mobile);
u.setUname(uname);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
DBTool.close(con, ps, rs);//关闭资源
}
return u;
}
封装更新数据的方法:
UserDaoImp.java:
@Override
public int update(User user) {
// TODO Auto-generated method stub
Connection con=DBTool.getConnection();
PreparedStatement ps=null;
String update="update myuser set health=? where id=?";//更新myuser表中的健康状态,按照id改,这些数据肯定也是通过user数据传过来
int result=0;
try {
ps=con.prepareStatement(update);//得到sql语句
ps.setString(1, user.getHealth());
ps.setString(2, user.getId());
result=ps.executeUpdate();//执行更新,返回一个result,更具这个结果判断更新是否成功
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
DBTool.close(con, ps, null);//关闭资源,结果集为null
}
return result;
}
至此,DAO层方法全部封装完成,UserDaoImp.java完成
管理员也有一个登录的界面
用户登录成功之后能看到自己的个人信息,能看到二维码
首先,在view包下面新建一个FXML文件UserMain.fxml,在这个fxml文件上打开Scene Builder进行界面的编辑
VBox里面放HBox,在HBox里面加Lable、TextField(姓名:文本框),ImageView(二维码),再适当调整位置,字号,等等。
有了一个界面,就要有对应的控制器,用户主界面控制器编写:UserIndexController.java
Main.java中,showUserMain(User user)中,这个user对象是如何传递过来的呢?在登录界面的控制器UserIndexController.java中的login()登录方法一旦运行起来,就会声明一个对象u,
private Main main;//设置一个入口程序类型的属性
public void setMain(Main main) {//加上属性的设置器
this.main = main;
}
@FXML
private void login(){
String mobile=txtmobile.getText();
String pwd=txtpwd.getText();
// 前边可以加检验功能
User u=ud.login(mobile, pwd);
if(u!=null){
// AlertController.showAlert("登录提示", "登录成功", "可以跳转到主界面");
main.showUserMain(u);
}else{
AlertController.showAlert("登录提示", "登录失败", "请检查手机号和密码");
}
// 后续可以加上清空文本框中数据的功能
}
改变入口程序Main.java关于控制器的代码
UserIndexController userIndexController=loader.getController();
userIndexController.setMain(this);//将入口程序本身传进去,此时就可以在登录之后,把主界面入口程序传递过去,在成功登录之后,就可以调用UserIndexController.java中的main对象,使用main.showUserMain(u);这个对象一旦成功了,Main.java中showUserMain方法里就可以得到用户对象了,用户对象再传递给UserMainController
public void showUserMain(User user){//showUserMain方法获取对象
FXMLLoader loader=new FXMLLoader();
loader.setLocation(this.getClass().getResource("/com/neuedu/mypass/view/UserMain.fxml"));
BorderPane bp=null;
try {
bp=loader.load();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Scene scene=new Scene(bp,400,500);
UserMainController umc=loader.getController();//用户对象再传递给UserMainController
umc.setUser(user);
umc.loadUserData();//就可以用loadUserData()方法把这个数据绑定到视图上
primaryStage.setScene(scene);
}
UserMainController.java
...
public void loadUserData(){//此方法实现数据绑定到视图上
txtuname.setText(user.getUname());
txtid.setText(user.getId());
mobile.setText(user.getMobile());
health.setText(user.getHealth());
}
第10个视频,登录跳转过程的梳理:
整个程序的入口,是在main类的start()方法里,当启动的时候,利用primaryStage里面的show()方法,来实现登录界面的呈现,同时加载了登录界面的控制器UserIndexController,利用这个控制器呢,把这个入口程序对象传递过去
接下来当你输入用户名和密码之后,点击登录按钮,
这个时候就会调用登录方法login(),完成登录数据的验证,得到一个用户类型的对象,接下来把这个对象传递给入口程序的showUserMain(u)方法。在这个登录控制器里已经持有了入口程序的对象private Main main,利用这个main对象调用它的showUserMain(u)方法,就可以把成功登录的用户对象传递过去
入口程序接收到这个用户对象之后,再把这个对象传递给主界面控制器,主界面控制器里有setUser()方法,以及loadUserData()方法,正好可以把接收到的用户数据绑定到已经事先声明好的控件类型的对象上
**然后这些对象数据,就可以呈现在界面上了。**另外,showUserMain()方法里面还有加载视图的功能
FXMLLoader loader=new FXMLLoader();//定义主界面视图
loader.setLocation(this.getClass().getResource("/com/neuedu/mypass/view/UserMain.fxml"));//得到视图的布局器
BorderPane bp=null;//定义新的舞台场景
//再把舞台场景传递给舞台对象,从而实现界面的转换
//