使用JavaFX開發桌面程序(一)

使用JavaFX開發桌面程序

注:我也是JAVA FX的初學者之一,本身在學習的時候踩了許多的坑,中文英文的資料查了很多,可是以爲FX技術和其餘熱門技術相比,教程仍是太少了。這裏就儘可能作一點微小的貢獻吧java

使用環境

注:寫這個只是爲了說明個人環境,使用和個人不同的環境在理解這篇教程的時候並無什麼問題,例如使用Windows平臺、使用Oracle JDK(這樣就不須要再單獨安裝FX組件了,能夠不用MAVEN)、使用Oracle的SceneBuilder。可能惟一一個比較影響體驗的就是不使用IDEA而是使用eclipse了app

  • Ubuntu18.04LTS
  • OpenJDK 1.8
  • IDEA(with MAVEN):使用MAVEN安裝FX環境(OpenJDK不附帶FX環境)
  • SceneBuilder(glounhq):這是一個fxml可視化設計環境,使用上不如C#,但起碼比純命令設計強一百倍

搭建JAVA FX環境

  1. 下載IDEA、OpenJDK1.八、SceneBuilder(glounhq).eclipse

    SceneBuilder下載地址:https://gluonhq.com/products/scene-builder/#downloadide

  2. 在IDEA中關聯SceneBuilder.關聯的目的是爲了以後能夠從IDEA快速打開SceneBuilder來設計頁面學習

    IDEA->File->Settings->Language->Java FX->輸入SceneBuilder的路徑ui

    若是是Linux環境,你會發現這個路徑還很差找,我是使用locate SceneBuilder命令找到的,路徑是:/opt/SceneBuilder/SceneBuilderthis

  3. 由於OpenJDK沒有FX環境,須要咱們本身安裝。爲了便於管理,咱們在這裏使用MAVEN設計

    1. 在IDEA中建立一個Java FX項目code

    2. 在項目名上右鍵,選擇'Add framework support',選擇MAVENxml

    3. 在pom.xml文件中加入如下依賴:

      <dependencies>
              <!-- https://mvnrepository.com/artifact/org.openjfx/javafx-controls -->
              <dependency>
                  <groupId>org.openjfx</groupId>
                  <artifactId>javafx-controls</artifactId>
                  <version>13</version>
              </dependency>
              <!-- https://mvnrepository.com/artifact/org.openjfx/javafx-fxml -->
              <dependency>
                  <groupId>org.openjfx</groupId>
                  <artifactId>javafx-fxml</artifactId>
                  <version>13</version>
              </dependency>
          </dependencies>

      設計流程

      這裏只寫一些我已經探索出來的設計流程,若是有不對的請指出~

      1. 先在Resources中建立fxml文件(之因此放在Resources文件夾下,是爲了加載的時候方便,以後能看到),建立完成後在文件名上右擊,選擇'Open in SceneBuilder',以後就能夠在SceneBuilder中進行可視化設計了。設計時要注意,對有響應的元素要在code欄下的fx:id中設置id,以便於以後的調用。設計完成後Ctrl+s保存文件

      2. 設計第一個加載的界面。這個能夠放在入口的java類的main方法下,舉個例子:

        package sample;
        
        import javafx.application.Application;
        import javafx.fxml.FXMLLoader;
        import javafx.scene.Parent;
        import javafx.scene.Scene;
        import javafx.stage.Stage;
        
        public class Main extends Application {
        
            @Override
            public void start(Stage primaryStage) throws Exception{
        
                Parent root = FXMLLoader.load(getClass().getClassLoader().getResource("Entry.fxml"));//從Resources中獲取資源
                primaryStage.setTitle("Course Registration System");
                primaryStage.setScene(new Scene(root, 800, 600));
                primaryStage.show();
            }
      3. 設計觸發器:

        對於每個Panel,咱們要指定一個觸發器類,這個是放在該fxml文件中的,例如IDEA中默認建立的就是AnchorPane對象,在它那一行就能找到:fx:controller="sample.MainController",這個MainController就是我建立的一個類

        以後,咱們能夠對該panel下各個控件設計觸發事件後的反映,這個能夠在SceneBuilder中填寫,在Code那一欄下面。設計了以後,它就會到咱們指定的那個觸發器類下尋找這個方法,若是沒有的話IDEA會提示你建立

        注意,觸發器類能夠建立多個,這樣更便於管理,下降耦合度

      4. 在觸發器中獲取fxml中的控件對象

        有時候,咱們須要在事件相應中獲取對象的值,例如設計登陸頁面時點擊'提交'的按鈕,咱們須要知道輸入框的字符串。這時候咱們能夠在觸發器中獲取這些元素,前提是咱們爲這些控件輸入了fx:id,它是全局性的,不容許重複。例如咱們能夠經過聲明:

        @FXML
            private TextField username;
            @FXML
            private TextField password;

        獲取兩個TextField對象下的值:

        usernameString=username.getText();
        passwordString=password.getText();
      5. 頁面跳轉

        咱們須要爲每個頁面設計一個Java類,例如我設計了一個SignIn_Student.java:

        package sample;
        
        import javafx.application.Application;
        import javafx.fxml.FXMLLoader;
        import javafx.scene.Parent;
        import javafx.scene.Scene;
        import javafx.stage.Stage;
        public class SignIn_Student extends Application{
            private  String usernameString;
            private  String passwordString;
            @Override
            public void start(Stage stage) throws Exception{
                Parent root = FXMLLoader.load(getClass().getClassLoader().getResource("SignIn_Student.fxml"));//加載頁面
                Scene anotherScene=new Scene(root);
                stage.setTitle("Please log in");
                stage.setScene(anotherScene);
                stage.show();
            }
        
        }
      6. TableView的使用

        這個控件用起來着實有點麻煩。折騰了很久。

        1. 咱們確定須要在某一個fxml頁面中加入了這個TableView,而且輸入了Table和它每個TableColumn的fx:id.

        2. 咱們須要爲有TableView的fxml文件單首創建一個控制器類,以後會說爲何

        3. 咱們須要建立一個類來表示要儲存的數據,例如我這裏建立了一個Courses.class:(下面的get和set方法是IDEA自動生成的)

          package sample;
          
          import javafx.beans.property.*;
          
          import java.time.LocalDate;
          import java.time.LocalTime;
          
          public class Courses {
          
              private final StringProperty department;
              private final StringProperty lecturer;
              private final ObjectProperty<LocalDate> Time;
              private final StringProperty location;
              private final IntegerProperty ID;
          
              public Courses(String name, String department, String lecturer, LocalDate time, String location, Integer ID) {
                  this.name = new SimpleStringProperty(name);
                  this.department = new SimpleStringProperty(department);
                  this.lecturer = new SimpleStringProperty(lecturer);
                  this.Time = new SimpleObjectProperty<LocalDate>(time);
                  this.location = new SimpleStringProperty(location);
                  this.ID = new SimpleIntegerProperty(ID);
              }
              //String,String,String, Date,String,Integer
              private final StringProperty name;
          
              public String getName() {
                  return name.get();
              }
          
              public StringProperty nameProperty() {
                  return name;
              }
          
              public void setName(String name) {
                  this.name.set(name);
              }
          
              public String getDepartment() {
                  return department.get();
              }
          
              public StringProperty departmentProperty() {
                  return department;
              }
          
              public void setDepartment(String department) {
                  this.department.set(department);
              }
          
              public String getLecturer() {
                  return lecturer.get();
              }
          
              public StringProperty lecturerProperty() {
                  return lecturer;
              }
          
              public void setLecturer(String lecturer) {
                  this.lecturer.set(lecturer);
              }
          
              public LocalDate getTime() {
                  return Time.get();
              }
          
              public ObjectProperty<LocalDate> timeProperty() {
                  return Time;
              }
          
              public void setTime(LocalDate time) {
                  this.Time.set(time);
              }
          
              public String getLocation() {
                  return location.get();
              }
          
              public StringProperty locationProperty() {
                  return location;
              }
          
              public void setLocation(String location) {
                  this.location.set(location);
              }
          
              public int getID() {
                  return ID.get();
              }
          
              public IntegerProperty IDProperty() {
                  return ID;
              }
          
              public void setID(int ID) {
                  this.ID.set(ID);
              }
          }
        4. 咱們須要實現的效果是,在加載這個頁面時,表格中自動加載數據。填寫咱們建立的控制器類以下:

          package sample;
          
          import javafx.collections.FXCollections;
          import javafx.collections.ObservableList;
          import javafx.fxml.FXML;
          import javafx.scene.control.TableColumn;
          import javafx.scene.control.TableView;
          import javafx.scene.control.TextField;
          
          import java.time.LocalDate;
          
          public class MainController {
              @FXML
              private TextField username;
              @FXML
              private TextField password;
              @FXML
              private TableView<Courses> allCoursesTable;
              @FXML
              private TableColumn<Courses,String> CourseNameAttribute;
              @FXML
              private TableColumn<Courses,String> DepartmentAttribute;
              @FXML
              private TableColumn<Courses,String> LectureAttribute;
              @FXML
              private TableColumn<Courses, LocalDate> TimeAttribute;
              @FXML
              private TableColumn<Courses,String> LocationAttribute;
              @FXML
              private TableColumn<Courses,Number> CourseIDAttribute;
              @FXML
              private void initialize() {
                  ObservableList<Courses> data= FXCollections.observableArrayList(new Courses("MACHINE LEARNING","COMPUTER","ZHANGYI",LocalDate.of(2012,01,01),"A101",4011));//建立ObservableList對象,將數據裝進去
                  CourseNameAttribute.setCellValueFactory(cellData->cellData.getValue().nameProperty());
                  DepartmentAttribute.setCellValueFactory(cellData->cellData.getValue().departmentProperty());
                  LectureAttribute.setCellValueFactory(cellData->cellData.getValue().lecturerProperty());
                  TimeAttribute.setCellValueFactory(cellData->cellData.getValue().timeProperty());
                  LocationAttribute.setCellValueFactory(cellData->cellData.getValue().locationProperty());
                  CourseIDAttribute.setCellValueFactory(cellData->cellData.getValue().IDProperty());
                  allCoursesTable.setItems(data);//加載數據
              }
          }

          這就是爲何要用單獨的控制器類了,不然initialize方法會在每次建立頁面的時候都加載一次,而只有某一個頁面有咱們說的這些Tabel和Column對象,會報錯的。

        5. 寫一個方法來跳轉到這個頁面。

        6. 如何實現頁面之間的傳參呢?

          對於要傳參的頁面,咱們就不能直接獲取parent對象了,而是先要獲取FXMLLoader對象:

          FXMLLoader fxmlLoader = new FXMLLoader(getClass().getClassLoader().getResource("MainPanel.fxml"));
          Parent root = fxmlLoader.load();
          MainController mc=fxmlLoader.getController();

          注意這個MainController是我爲這個頁面寫的控制器類

          獲取了Controller對象後,咱們就能夠調用方法,將參數傳進去了:

        mc.setPassword(pass);
                mc.setUsername(user);
                mc.handleAllCourses();

        我在MainController這個類中是這樣寫的:

        public void setUsername(String username){
                usernameString=username;
            }
            public void setPassword(String password){
                passwordString=password;
            }

        這就是入門的FX教程了,有了這些基本的方法,相信設計一個稍微複雜一點的桌面應用程序已經不是問題了。

相關文章
相關標籤/搜索