前言

在学习Swing后,听老师说使用Java写界面还可以使用JavaFX。课后,便去了解。JavaFX是甲骨文公司07年推出的期望应用于桌面开发领域的技术。在了解了这个技术几天后,便使用它完成Java课程的大作业一个日记系统。(因为前面有Swing的基础,所以入门JavaFX比较快)还需要说明,博主是使用SceneBuilder配合JavaFX做的日记系统。
下面将介绍使用JavaFX完成日记系统的详细思路以及一些关键的步骤,完整工程代码会附在文末。

前期的入门准备

先介绍一下博主入门JavaFx的过程,希望可以对毫无基础的小伙伴有一个帮助。

博主先是花了两三天时间跟着B站上面一个Up主的视频入坑学习。现在网上认真讲JavaFX技术的资料不多,学的人也少,这个技术还有种局势有点不妙的感觉,于是这个Up主每次视频一开讲都说:“欢迎大家收看JavaFX没人看系列”,每次博主都会默默评论我在看我在看,这个Up主实在很有趣。但是有一点不好,博主觉得Up主的语速有点慢(可能是赶着做大作业比较心急吧),每次播放都是放2倍速,2倍速的语句听起来刚刚好。需要注意,一定要慢慢学不能急!

B站JavaFX技术学习视频链接:https://space.bilibili.com/5096022/channel/detail?cid=16953

前面提到过博主是使用SceneBuilder对界面进行布局,因为时间着急所以就没有写代码布局,而是使用这个工具。在正式开始写日记系统之前,看了一个使用SceneBuilder搭配做联系簿小项目的教程。若是也准备使用SceneBuilder完成界面布局也可以拿这个项目练手。

使用SceneBuilder搭配做联系簿项目教程:https://code.makery.ch/zh-cn/library/javafx-tutorial/

这个教程网站的站长是一个优秀的国外程序员,这个网站几乎全是关于JavaFX技术教程的网站,这个站长喜欢做教育所以网站上的教程都通俗易懂,很适合入门学习!

易百教程的JavaFX教程也不错,也有教使如何用SceneBuilder:https://www.yiibai.com/javafx/javafx-tutorial-for-beginners.html

日记系统的一个整体观感


登录视图

注册视图



忘记密码视图

主视图

写日记视图

查找日记视图

日记实现的思路

日记系统的实现使用了MVC的思想(默认大家都理解了MVC的思想),但是这里不是严格按照这种思想实现。看下面的工程目录树,了解整体的框架。

下面我们从主控制器开始讲解:

主控制器

在看下面之前列要求没有使用过JavaFX的小伙伴至少把易百教程的JavaFX快速入门看一遍并且敲一遍。

主控制器是控制所有视图之间的切换。每一个视图(登录、注册、忘记密码、写日记和查找日记)就是一个scene,视图在主控制器的stage中切换,使用stage.setScene(scene);每切换到一个视图时就会创建对应的控制器并且将主控制器的引用传给该控制器对象,使得可以调用主控制器的方法切换到其他视图

当程序一启动显示的登录界面,但是按下注册按钮后,就会调用lgController.mainApp.showRegistView()方法切换到注册视图。

public class MainApp extends Application {
//视图展现的“舞台”
private Stage stage;
//“场景”(视图)
private Scene scene;
//标识当前用户
private User user; @Override
public void start(Stage primaryStage) {
try {
stage = primaryStage;
//显示登录界面
showLoginView();
//调用show方法显示
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
} /**
* 显示登录界面
*/
public void showLoginView() {
try {
stage.setTitle("Login");
stage.getIcons().clear();
stage.getIcons().add(new Image("file:images/login.png"));
//创建登录控制器对象
LoginViewController lgController = (LoginViewController)replaceSceneContent("login/LoginView.fxml");
//将主控制器的引用传给登录控制器对象
lgController.setMainApp(this);
}catch(Exception e) {
e.printStackTrace();
}
} /**
* 显示注册界面
*/
public void showRegistView() {
try { stage.setTitle("Regist");
stage.getIcons().clear();
stage.getIcons().add(new Image("file:images/regist.png")); FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("regist/RegistView.fxml"));
BorderPane bp = (BorderPane)loader.load();
scene = new Scene(bp);
stage.setScene(scene);
stage.setResizable(false); RegistViewController regController = (RegistViewController)loader.getController();
System.out.println(regController);
regController.setMainApp(this); }catch(Exception e) {
e.printStackTrace();
}
} //省略显示其他视图的方法...... /**
* 显示指定的视图
*/
private Object replaceSceneContent(String fxmlFile) {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource(fxmlFile)); AnchorPane ap = null;
try {
ap = (AnchorPane)loader.load();
}catch(IOException e) {
e.printStackTrace();
} scene = new Scene(ap);
stage.setScene(scene);
stage.setResizable(false); return loader.getController();
} public static void main(String[] args) {
launch(args);
}
}

登录

以登录为例子介绍一下如何使用SceneBuilder与JavaFX结合。SceneBuilder是需要安装的,没有安装的小伙伴请看下易百的教程。

创建LoginView.fmxl文件(SceneBuilder构造界面产生的内容将写在该文件里),右击该文件选择open with SceneBuilder。

在创建好LoginView.fxml文件后要在相同包下创建控制器,不然在SceneBuilder设置该视图控制器时会找不到控制器类。

SceneBuilder构造视图


在布局完后,是可以使用Preview预览功能先查看效果

控制器LoginViewController.java

与视图中关联的组件和方法要一律使用@FXML注解

public class LoginViewController {
//对主控制器的引用
private MainApp mainApp; @FXML
private Label userNameLabel; @FXML
private Label passwordLabel; @FXML
private Button LoginButton; @FXML
private Button registButton; @FXML
private ImageView leftImageView; @FXML
private TextField userNameField; @FXML
private TextField passwordField; @FXML
private Label errorInfoLabel; /**
* 获取主控制器的引用
*/
public void setMainApp(MainApp mainApp) {
this.mainApp = mainApp;
} //在fxml文件被加载后自动调用
@FXML
private void initialize() {
//设置用户名输入框和密码输入框前的图标、左边图片
userNameLabel.setGraphic(new ImageView(new Image("file:images/user.png")));
passwordLabel.setGraphic(new ImageView(new Image("file:images/password.png")));
leftImageView.setImage(new Image("file:images/leftimage.png"));
} /**
* 处理登录 到主界面的事件
*/
@FXML
private void handleLoginButtonAction() {
// ... 对用户名和密码的判断、跳转主视图
} /**
* 处理注册按钮事件
*/
@FXML
private void handleRegistButtonAction() {
//显示注册视图
mainApp.showRegistView();
} /**
* 处理忘记密码事件
*/
@FXML
private void handleForgetPasswordAction() {
//显示忘记密码视图
mainApp.showForgetView();
}
}

登录功能的实现思路

  • 在SceneBuilder中完成组件布局

  • 在相同的包下面创建控制器,控制器中需要使用@FXML注解与视图中组件相关联的组件对象,如这里的LoginButton、registButton等。我们在控制器中对这些被注解的组件操作,就是对视图中的组件操作。

    在控制器中使用@FXML注解的方法,是可以作为事件触发时的处理方法。

  • 右击fxml文件,选择open with SceneBuilder,设置视图的控制器、关联组件以及组件相应事件处理该调用的处理方法。

  • 每次在SceneBuilder中修改完fxml文件退出后,都应该刷新工程。因为改变可能不会立即生效。

这就是博主实现登录功能的一个思路,后面每个功能的基础实现差不多都是这样:先布局然后写控制器再关联。登录功能要处理的内容很少,就只有用户名和密码的合法性校验,因此对具体实现不多介绍(文末项目源代码中有详细过程)。

后面对其他功能的介绍主要侧重在于该功能的作用和做该功能时博主遇到的难点。

注册

注册主要涉及到对用户输入合法性的检测。注册成功后可以直接跳转主视图或者登录视图。

忘记密码

忘记密码的实现也很简单,先是用户输入用户名,若用户名存在就可以跳转密保问题回答视图,否则弹出提示框该用户名不存在。
在密保问题视图,若是回答正确密保问题就可以跳转重置密码视图,否则弹出提示框答案错误。
若重置的密码符合密码要求规范,就重置成功跳转登录视图,否则重新输入重置的密码。

主视图

主视图主要起一个选择菜单的作用,让当前登录用户选择是写日记还是登录日记。

写日记

实现写日记时使用了两个有趣的组件:DatePicker和HTMLEditor。DatePicker可以弹出日期供用户选择,使用方便。

HTMLEditor是使用在Web的富文本编辑器,这里博主使用这个组件来使用户编辑日记格式更加丰富一点。

查找日记

在左侧列表显示出所有日记,在列表中选中相应日记后,右边的详细信息会显示选中日记的详细内容。在点击编辑按钮后,右边详情区便可以被修改和更新。上方还设置了根据日记的标题进行查找日记,因为根据其他关键字搜索日记都是大同小异所以仅实现了依据标题查找。

模型类

Diary类和User类的对象就是数据库中的日记和用户表的实体。

工具类

CheckValidTool类

在各类中使用正则对用户名、密码以及邮箱的合法性检查

DialogTool类

因为在用户输入或者进行提交等操作时,会出现错误警告等信息,需要弹出提示框进行提醒。若在控制器中每一处可能会出错的地方都写提示框代码就会显得代码臃肿,于是将需要用到了提示框写成一个工具类方便调用。

VerificationCodeTool类

这是一个算术运算验证码的工具类,负责产生一个三元四则算术运算验证码。实现比较简单。可以贴代码看一下:

public class VerificationCodeTool {

	/**
* 生成四则算术验证码
*
* @return Map<String,Integer> 生成的四则运算验证码字符串和正确的结果
*/
public static Map<String,Integer> generateArithmeticVerification() {
//生成三个随机操作数
Random random = new Random();
int a = random.nextInt(10)+1;
int b = random.nextInt(10)+1;
int c = random.nextInt(10)+1; //从'+', '-', '*', '/'随机选择两个运算符
char[] OperatorArray = new char[] {'+', '-', '*', '/'};
int opIndex1 = random.nextInt(4);
int opIindx2 = random.nextInt(4);
char op1 = OperatorArray[opIndex1];
char op2 = OperatorArray[opIindx2]; int result = 0; //算术运算的真实结果
if(comparisonOpPriority(op1, op2)) {
result = calculate(a, b, op1);
result = calculate(result, c, op2);
}else {
result = calculate(b, c, op2);
result = calculate(a, result, op1);
}
//System.out.print("请输入"+ a + op1+ b + op2 + c + "=?的答案:" ); //提示用户输入验证码的答案
String opExp = ""+a + op1+ b + op2 + c ;
Map<String,Integer> resExp = new HashMap<>();
resExp.put(opExp, result);
return resExp;
} /**
* 二元一则运算
* @param a 第一个操作数
* @param b 第二个操作数
* @param op 操作符
* @return int 运算结果
*/
public static int calculate(int a, int b, char op) {
int calResult = 0;
switch(op)
{
case '+':
calResult = a+b;
break;
case '-':
calResult = a-b;
break;
case '*':
calResult = a*b;
break;
case '/':
calResult = a/b;
break;
}
return calResult;
} /**
* 比较操作符的优先级
* @param op1 第一个操作符
* @param op2 第二个操作符
* @return boolean
*/
public static boolean comparisonOpPriority(char op1, char op2)
{
boolean op1HasHighPriority = true;
switch(op1) //若是op1和op2为/或者*时,默认op1的优先级高
{
case '-':
case '+':
if(op2=='*' || op2=='/')
op1HasHighPriority = false;
break;
}
return op1HasHighPriority;
}
}

JDBCTool类

数据库连接工具类。与数据库交互时使用的是PreparedStatement语句。连接数据库是使用Properties配置文件方式。操作数据库时时刻需要注意的就是使用完资源后要记得释放资源!

小结

了解JavaFX以及使用其完成日记系统差不多花了一个星期多一点,其中主要靠使用SceneBuilder完成界面布局才使得方便许多。博主其实觉得JavaFX和Qt很相似,一个是Java一个是C++用来写界面的只是语言种类不同。虽然这个日记系统真的简单,但是使用新的技术做出这个小成品还是满开心的。在做完这个小成品后,我觉得以后接触新知识需要注意以下两点:

  • 官方文档真的很重要

  • 看视频教学不要只看一定要跟着做(不管视频中的示例多么简单)或者看完后独立实现一次

    而且官方网站也有教程的(但是是英文的),不要局限于别人博客中的教程,多看官网教程

  • 学习要慢,不能急

可能这些注意点很多人已经提过了,但是毕竟是博主亲身体会过,还是有必要总结记下来,在学习之路上增加一点经验值。

JavaFX技术博主还是了解的很肤浅,也还在学习,有问题可以留言我们一起交流~

日记系统源码地址: https://github.com/Sakuraxx/DiarySystem_JavaFX

icon素材网址:https://www.iconfont.cn/collections/detail?cid=139

JavaFX——简单的日记系统的更多相关文章

  1. 【小型系统】简单的刷票系统(突破IP限制进行投票)

    一.前言 相信大家平时肯定会收到朋友发来的链接,打开一看,哦,需要投票.投完票后弹出一个页面(恭喜您,您已经投票成功),再次点击的时候发现,啊哈,您的IP(***.***.***.***)已经投过票了 ...

  2. Linux内核设计第三周——构造一个简单的Linux系统

    Linux内核设计第三周 ——构造一个简单的Linux系统 一.知识点总结 计算机三个法宝: 存储程序计算机 函数调用堆栈 中断 操作系统两把宝剑: 中断上下文的切换 进程上下文的切换 linux内核 ...

  3. 《Linux内核分析》第三周 构建一个简单的Linux系统MenuOS

    [刘蔚然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000] WEEK THREE ...

  4. 第三节 构造一个简单的Linux系统MenuOS——20135203齐岳

    第三节 构造一个简单的Linux系统MenuOS By 20135203齐岳 Linux内核源代码 arch/ 支持不同cpu的源代码 Documentations/ 文档存储 init/ 内核启动相 ...

  5. Linux内核分析第三周学习总结:构造一个简单的Linux系统MenuOS

    韩玉琪 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.Linux内 ...

  6. 一个简单的CS系统打包过程图文版

    一个简单的CS系统打包过程图文版 1.     打包内容 1.1.  此次打包的要求和特点 主工程是一个CS系统: 此CS系统运行的先决条件是要有.Net Framework 3.5: 主工程安装完成 ...

  7. Linux下一个简单的日志系统的设计及其C代码实现

    1.概述 在大型软件系统中,为了监测软件运行状况及排查软件故障,一般都会要求软件程序在运行的过程中产生日志文件.在日志文件中存放程序流程中的一些重要信息, 包括:变量名称及其值.消息结构定义.函数返回 ...

  8. Oracle 最简单的随系统自己主动启动

    Oracle 最简单的随系统自己主动启动 俗话说用户是上帝,他们有时候提出一个问题很的简单,就仅仅须要一句话,一分钟就完事了.可是拿到我们DBA来说,可能至少得半个小时甚至半个月才干满足他的一句话.有 ...

  9. 简单的刷票系统(突破IP限制进行投票) (转)

    前言 相信大家平时肯定会收到朋友发来的链接,打开一看,哦,需要投票.投完票后弹出一个页面(恭喜您,您已经投票成功),再次点击的时候发现,啊哈,您的IP(***.***.***.***)已经投过票了,不 ...

随机推荐

  1. QT—QTextEdit控件显示日志

    功能:利用QTextEdit开发一个日志显示窗口.没有太多操作,需要实现的是日志自动向上滚动,总体的日志量可以控制在x行(比如300行)以内:其他的应用功能我后面继续添加 #include <Q ...

  2. deepin 开机进入 initramfs,无法开机

    原因 这个问题多是由于不正常关机造成文件系统出问题导致的 解决 fsck -t ext4 /dev/sda6 这个命令用于修复磁盘,一直选择y即可. 如果sda6 不行就换位sda1 再试. 执行完后 ...

  3. 读取 ini 配置文件

    ini 配置文件格式:db_config.ini '''[section]option=value''' [DATABASE1] host=192.168.30.80 port= user=testa ...

  4. SpringBoot报错:nested exception is org.apache.ibatis.executor.ExecutorException: No constructor found in com.tuyrk.test.User matching [java.lang.Long, java.lang.String, java.lang.String]

    错误提示: Caused by: org.apache.ibatis.executor.ExecutorException: No constructor found in com.tuyrk._16 ...

  5. Nginx的gzip

    webpack  compression-webpack-plugin => .gz CompressionPlugin = require("compression-webpack- ...

  6. 循环结构for

    教程:高能:语句结构都是由关键字开头,用冒号结束! 一:语句结构 for <variable> in <sequence>:    <statements>else ...

  7. swust oj 987

    输出用先序遍历创建的二叉树是否为完全二叉树的判定结果 1000(ms) 10000(kb) 2553 / 5268 利用先序递归遍历算法创建二叉树并判断该二叉树是否为完全二叉树.完全二叉树只能是同深度 ...

  8. java中List<Map<String, Object>>关于null的判断

    List<Map<String, Object>> selectTmFileInfo = fileInfoService.selectTmFileInfoByToken(cTo ...

  9. sqlserver 电脑重启以后服务突然无法启动 报错

    可能是sql server 评估期已过  在升级中输入产品密钥试试

  10. APP测试流程的总结

    本规范基于app大小版本测试经验总结. 第一阶段:需求分析(技术+产品) 1. 新需求是否合理 2. 新旧需求时否存在冲突 3. 理出测试重点 4. 估算测试时间 5. 不熟悉的需求点,确认(负责人, ...