在上一篇文章中,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"之后,就可以正常运行了。
网友评论