在學習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