美文网首页
SpringBoot整合JavaFx、Jfoenix开发一个简单

SpringBoot整合JavaFx、Jfoenix开发一个简单

作者: 程就人生 | 来源:发表于2020-06-20 21:48 被阅读0次

在上一篇文章中,IntelliJ IDEA的开发环境已经安装好了,现在就来一个简单的demo。想一想实际的应用场景,一般的桌面应用,都是需要经过登录页面,登录过后进入主页面;所以现在就做个简单的登录页面,登录过后跳转至主页面;下面上代码。

首先,pom文件引入必要的架包;

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example.app</groupId>
    <artifactId>JavaFx-First</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--字体架包-->
        <dependency>
            <groupId>de.jensd</groupId>
            <artifactId>fontawesomefx</artifactId>
            <version>8.9</version>
        </dependency>
        <dependency>
            <groupId>org.controlsfx</groupId>
            <artifactId>controlsfx</artifactId>
            <version>8.40.14</version>
        </dependency>
        <!---->
        <dependency>
            <groupId>com.jfoenix</groupId>
            <artifactId>jfoenix</artifactId>
            <version>8.0.7</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

第二步,入口文件;

package com.example.app;

import com.example.app.controller.LoginController;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

/**
 * 入口程序
 * @author 程就人生
 * @Date
 */
public class MyApp extends Application {

    //主窗口
    private Stage mainStage;

    @Override
    public void start(Stage primaryStage) throws Exception{
        mainStage = primaryStage;
        //加载登录页面
        FXMLLoader loader = new FXMLLoader(getClass().getResource("/login.fxml"));
        Parent root = loader.load();
        LoginController controller = loader.getController();
        controller.setApp(this);
        Scene scene = new Scene(root);
        //设置样式
        //scene.getStylesheets().add(getClass().getResource("/css/jfoenix-components.css").toExternalForm());
        //绑到顶层容器上
        primaryStage.setScene(scene);
        //设置标题
        primaryStage.setTitle("第一个JavaFx程序");
        //展示窗口
        primaryStage.show();
    }

    /**
     * 隐藏当前窗口
     */
    public void hideWindow(){
        mainStage.hide();
    }
}

第三,fxml文件;
登录login.fxml文件;

<?import com.jfoenix.controls.JFXButton?>
<?import com.jfoenix.controls.JFXPasswordField?>
<?import com.jfoenix.controls.JFXTextField?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane prefHeight="400.0" prefWidth="464.0" xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.app.controller.LoginController">
   <children>
      <JFXButton fx:id="loginButton" layoutX="167.0" layoutY="262.0" mnemonicParsing="false" onMouseClicked="#login" prefHeight="30.0" prefWidth="202.0" styleClass="button-raised" text="登录" />
      <JFXPasswordField fx:id="password" layoutX="167.0" layoutY="200.0" promptText="请输入密码" />
      <JFXTextField fx:id="username" layoutX="167.0" layoutY="136.0" promptText="请输入用户名" />
      <Label layoutX="113.0" layoutY="141.0" text="用户名" />
      <Label layoutX="113.0" layoutY="205.0" text="密码" />
   </children>
</AnchorPane>

主页面main.fxml文件;

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.app.controller.MainController">
   <children>
      <Label layoutX="66.0" layoutY="149.0" prefHeight="132.0" prefWidth="457.0" text="这里是主页面" />
      <Button layoutX="147.0" layoutY="266.0" mnemonicParsing="false" text="Button" />
   </children>
</AnchorPane>

第四,Controller文件;
登录LoginController文件;

package com.example.app.controller;

import com.example.app.MyApp;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXPasswordField;
import com.jfoenix.controls.JFXTextField;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.stage.Stage;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

/**
 *
 * 登录
 * @author 程就人生
 * @Date
 */
@Component
public class LoginController implements Initializable {

    @FXML
    JFXTextField username;

    @FXML
    JFXPasswordField password;

    @FXML
    JFXButton loginButton;

    private MyApp myApp;

    public void setApp(MyApp myApp) {
        this.myApp = myApp;
    }

    /**
     * 初始化方法
     * @param location
     * @param resources
     */
    @Override
    public void initialize(URL location, ResourceBundle resources) {

    }

    /**
     * 登录操作
     */
    @FXML
    public void login(){
        //验证用户名是否为空
        if(StringUtils.isEmpty(username.getText())){
            Alert alert = new Alert(Alert.AlertType.ERROR);
            alert.setContentText("用户名不能为空!");
            alert.show();
            return;
        }
        if(StringUtils.isEmpty(password.getText())){
            Alert alert = new Alert(Alert.AlertType.ERROR);
            alert.setContentText("密码不能为空!");
            alert.show();
            return;
        }
        myApp.hideWindow();
        //加载登录页面
        FXMLLoader loader = new FXMLLoader(myApp.getClass().getResource("/main.fxml"));
        Parent root = null;
        try {
            root = loader.load();
        } catch (IOException e) {
            e.printStackTrace();
        }
        MainController controller = loader.getController();
        controller.setApp(myApp);
        //开启一个顶级容器
        Stage stage = new Stage();
        controller.setStage(stage);
        Scene scene = new Scene(root);
        stage.setScene(scene);
        //设置标题
        stage.setTitle("登录后的主页面");
        //展示窗口
        stage.show();
    }
}

主页面MainController文件;

package com.example.app.controller;

import com.example.app.MyApp;
import javafx.fxml.Initializable;
import javafx.stage.Stage;
import org.springframework.stereotype.Component;
import java.net.URL;
import java.util.ResourceBundle;

/**
 * 主页面
 * @author 程就人生
 * @Date
 */
@Component
public class MainController implements Initializable {

    private MyApp myApp;

    private Stage stage;

    public void setApp(MyApp myApp) {
        this.myApp = myApp;
    }

    public void setStage(Stage _stage){
        this.stage = _stage;
    }

    /**
     * 初始化方法
     * @param location
     * @param resources
     */
    @Override
    public void initialize(URL location, ResourceBundle resources) {

    }
}

最后,测试;
运行主文件,输入用户名密码,页面跳转;

登录页面
登录后的主页面

框架里引入了Jfoenix框架后,页面已经有一点样式了,不像原生的swing组件那么粗糙,如果想要漂亮一点的UI,还需要继续学习这几款框架是如何使用的。

一个应用只有一个入口程序,入口程序继承了Application抽象类,通过重写start方法启动了主程序,抽象类里有两种主题,还有两个launch抽象方法,init、start、stop等方法。


public abstract class Application {
    //两种主题
    public static final String STYLESHEET_CASPIAN = "CASPIAN";
 
    public static final String STYLESHEET_MODENA = "MODENA";
    //运行方法
    public static void launch(Class<? extends Application> appClass, String... args) {
        LauncherImpl.launchApplication(appClass, args);
    }

    public static void launch(String... args) {
        // Figure out the right class to call
        StackTraceElement[] cause = Thread.currentThread().getStackTrace();

        boolean foundThisMethod = false;
        String callingClassName = null;
        for (StackTraceElement se : cause) {
            // Skip entries until we get to the entry for this class
            String className = se.getClassName();
            String methodName = se.getMethodName();
            if (foundThisMethod) {
                callingClassName = className;
                break;
            } else if (Application.class.getName().equals(className)
                    && "launch".equals(methodName)) {

                foundThisMethod = true;
            }
        }

        if (callingClassName == null) {
            throw new RuntimeException("Error: unable to determine Application class");
        }

        try {
            Class theClass = Class.forName(callingClassName, false,
                               Thread.currentThread().getContextClassLoader());
            if (Application.class.isAssignableFrom(theClass)) {
                Class<? extends Application> appClass = theClass;
                LauncherImpl.launchApplication(appClass, args);
            } else {
                throw new RuntimeException("Error: " + theClass
                        + " is not a subclass of javafx.application.Application");
            }
        } catch (RuntimeException ex) {
            throw ex;
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    public Application() {
    }
   //初始化抽象方法
    public void init() throws Exception {
    }
    //开始抽象方法;
    public abstract void start(Stage primaryStage) throws Exception;
    
    public void stop() throws Exception {
    }

    private HostServices hostServices = null;

    public final HostServices getHostServices() {
        synchronized (this) {
            if (hostServices == null) {
                hostServices = new HostServices(this);
            }
            return hostServices;
        }
    }

    public final Parameters getParameters() {
        return ParametersImpl.getParameters(this);
    }
   
    public final void notifyPreloader(PreloaderNotification info) {
        LauncherImpl.notifyPreloader(this, info);
    }
 
    public static abstract class Parameters {
      
        public Parameters() {
        }

        public abstract List<String> getRaw();

        public abstract List<String> getUnnamed();

      
        public abstract Map<String, String> getNamed();

    }

    private static String userAgentStylesheet = null;

    public static String getUserAgentStylesheet() {
        return userAgentStylesheet;
    }

    public static void setUserAgentStylesheet(String url) {
        userAgentStylesheet = url;
        if (url == null) {
            PlatformImpl.setDefaultPlatformUserAgentStylesheet();
        } else {
            PlatformImpl.setPlatformUserAgentStylesheet(url);
        }
    }
}

另外还有一个非常非常重要的类,那就是Stage,该类继续了Window类,该类是顶级的JavaFX容器,要打开一个窗口,必须有Stage类做底层容器。所以,从登陆页面到主页面,又新new了一个stage,来放置主页面的一系列组件。

这是第一个JavaFx的简单应用,通过拖拽的方式生成了登录页面和主页面,也遇到了一些问题,想必其他的新手也会遇到;那就是在拖拽的过程中,控件的id在一开始时是这样写的id="username",结果导致控制层的username.getText()一直报空指针错误,把id="username"改为fx:id="username"之后,就可以正常运行了。

相关文章

网友评论

      本文标题:SpringBoot整合JavaFx、Jfoenix开发一个简单

      本文链接:https://www.haomeiwen.com/subject/ubggxktx.html