在学习Swing后,听老师说使用Java写界面还可使用JavaFX。课后,便去了解。JavaFX是甲骨文公司07年推出的指望应用于桌面开发领域的技术。在了解了这个技术几天后,便使用它完成Java课程的大做业一个日记系统。(由于前面有Swing的基础,因此入门JavaFX比较快)还须要说明,博主是使用SceneBuilder
配合JavaFX作的日记系统。
下面将介绍使用JavaFX完成日记系统的详细思路以及一些关键的步骤,完整工程代码会附在文末。html
先介绍一下博主入门JavaFx的过程,但愿能够对毫无基础的小伙伴有一个帮助。
java
博主先是花了两三天时间跟着B站上面一个Up主的视频入坑学习。如今网上认真讲JavaFX技术的资料很少,学的人也少,这个技术还有种局势有点不妙的感受,因而这个Up主每次视频一开讲都说:“欢迎你们收看JavaFX没人看系列”,每次博主都会默默评论我在看我在看,这个Up主实在颇有趣。可是有一点很差,博主以为Up主的语速有点慢(多是赶着作大做业比较心急吧),每次播放都是放2倍速,2倍速的语句听起来刚恰好。须要注意,必定要慢慢学不能急!
git
B站JavaFX技术学习视频连接:https://space.bilibili.com/5096022/channel/detail?cid=16953程序员
前面提到过博主是使用SceneBuilder对界面进行布局,由于时间着急因此就没有写代码布局,而是使用这个工具。在正式开始写日记系统以前,看了一个使用SceneBuilder搭配作联系簿小项目的教程。如果也准备使用SceneBuilder完成界面布局也能够拿这个项目练手。
github
使用SceneBuilder搭配作联系簿项目教程:https://code.makery.ch/zh-cn/library/javafx-tutorial/数据库
这个教程网站的站长是一个优秀的国外程序员,这个网站几乎全是关于JavaFX技术教程的网站,这个站长喜欢作教育因此网站上的教程都通俗易懂,很适合入门学习!框架
易百教程的JavaFX教程也不错,也有教使如何用SceneBuilder:https://www.yiibai.com/javafx/javafx-tutorial-for-beginners.htmldom
日记系统的实现使用了MVC
的思想(默认你们都理解了MVC的思想),可是这里不是严格按照这种思想实现。看下面的工程目录树,了解总体的框架。yii
下面咱们从主控制器开始讲解:编辑器
在看下面以前列要求没有使用过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设置该视图控制器时会找不到控制器类。
在布局完后,是可使用Preview预览功能先查看效果
与视图中关联的组件和方法要一概使用@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类的对象就是数据库中的日记和用户表的实体。
在各种中使用正则对用户名、密码以及邮箱的合法性检查
由于在用户输入或者进行提交等操做时,会出现错误警告等信息,须要弹出提示框进行提醒。若在控制器中每一处可能会出错的地方都写提示框代码就会显得代码臃肿,因而将须要用到了提示框写成一个工具类方便调用。
这是一个算术运算验证码的工具类,负责产生一个三元四则算术运算验证码。实现比较简单。能够贴代码看一下:
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; } }
数据库链接工具类。与数据库交互时使用的是PreparedStatement
语句。链接数据库是使用Properties配置文件方式。操做数据库时时刻须要注意的就是使用完资源后要记得释放资源!
了解JavaFX以及使用其完成日记系统差很少花了一个星期多一点,其中主要靠使用SceneBuilder完成界面布局才使得方便许多。博主其实以为JavaFX和Qt很类似,一个是Java一个是C++用来写界面的只是语言种类不一样。虽然这个日记系统真的简单,可是使用新的技术作出这个小成品仍是满开心的。在作完这个小成品后,我以为之后接触新知识须要注意如下两点:
官方文档真的很重要
看视频教学不要只看必定要跟着作(无论视频中的示例多么简单)或者看完后独立实现一次
并且官方网站也有教程的(可是是英文的),不要局限于别人博客中的教程,多看官网教程
学习要慢,不能急
可能这些注意点不少人已经提过了,可是毕竟是博主亲身体会过,仍是有必要总结记下来,在学习之路上增长一点经验值。
JavaFX技术博主仍是了解的很肤浅,也还在学习,有问题能够留言咱们一块儿交流~
日记系统源码地址: https://github.com/Sakuraxx/DiarySystem_JavaFX
icon素材网址:https://www.iconfont.cn/collections/detail?cid=139