可携带数据跳转

1. 新增可携带数据跳转的功能
2. 完善README
3. 修改示例
This commit is contained in:
yangsuiyu
2020-04-07 21:53:25 +08:00
parent 119436dc3b
commit 7c807d4b39
39 changed files with 1097 additions and 277 deletions

View File

@@ -32,7 +32,6 @@ Language: [中文](README.md)
- [Specification](#specification)
- [How to Use](#how-to-use)
- [Example Code](#example-code)
- [Deficiencies](#deficiencies)
[How to Use JavaFX-Plus](#how-to-use-javafX-plus)
@@ -452,7 +451,7 @@ In JavaFX application, we always need to switch between multiple windows, such a
#### Specification
The JavaFX-Plus stipulates that if we need an annotated with `@FXRedirect` method to handle redirection, the return value must be Stirng property and return the name of registered Controller. For example, if we need redirecting to login success interface whose conttroller named SuccessController, we should write `return "SuccessController"` in the method handling redirection.
The JavaFX-Plus stipulates that if we need an annotated with `@FXRedirect` method to handle redirection, the return value must be Stirng property or FXRedirectParam class, which all should provide the name of registered Controller. For example, if we need redirecting to login success interface whose controller named SuccessController, we should write `return "SuccessController"` in the method handling redirection. But the way above had not transfer data to anothor stage. If we need to transfer data to anothor stage, we should return url or FXRedirectParam, the usage has follows:
#### How to Use
@@ -465,44 +464,103 @@ The JavaFX-Plus stipulates that if we need an annotated with `@FXRedirect` metho
}
@FXML
@FXRedirect(close = false)
@FXRedirect(close = false) //test popup
public String redirectToDialog() {
return "DialogController";
}
@FXML
@FXRedirect //redirect to success page with query url
public String redirectToSuccessWithQuery() {
return "SuccessController?username=" + usernameTF.getText();
}
@FXML
@FXRedirect //redirect to success page with param
public FXRedirectParam redirectToSuccessWithParam() {
//SuccessController is the name of controller which is redirected to
FXRedirectParam params = new FXRedirectParam("SuccessController");
params.addParam("username", usernameTF.getText());
return params;
}
@FXML
@FXRedirect //redirect to success page with query and param
public FXRedirectParam redirectToSuccessWithAll() {
//SuccessController is the name of controller which is redirected to
FXRedirectParam params = new FXRedirectParam("SuccessController");
params.addParam("username", usernameTF.getText());
params.addQuery("token", new Date().toString());
return params;
}
```
The boolean value of close marks that if close the current window, and the default value is true, which means that the current window will be closed when redirecting to anothor window.
If we need to transform data to another controller when redirecting to it, we can choose to return URL string, for example `return "SuccessController?name=JavaFX&password=Plus"`, or return class `FXRedirectParam` provided by JavaFX-Plus, with this way, we can choose addParam() or addQuery to transform parameters data according to your needs.
2. Create the login Controller
1. Firstly, we design an API of data which transforms from LoginController to SuccessController, which as follows:
```java
username: the name of user to login
password: the password of user to login
token: a token to login
```
The example code :
```java
@FXController(path = "redirectDemo/login.fxml")
@FXWindow(title = "redirectDemo", mainStage = true)
public class LoginController extends FXBaseController {
@FXML
private TextField usernameTF;
@FXML
private PasswordField passwordPF;
@FXML
public void registerClick() {
public void registerClick() { //click the "register" button
redirectToRegister();
}
@FXRedirect
public String redirectToRegister() {
public String redirectToRegister() { //redirect to register page
return "RegisterController";
}
@FXML
@FXRedirect(close = false)
@FXRedirect(close = false) //popup
public String redirectToDialog() {
return "DialogController";
}
@FXML
@FXRedirect //redirect to success page with query url
public String redirectToSuccessWithQuery() {
return "SuccessController?username=" + usernameTF.getText() + "&password=" + passwordPF.getText();
}
@FXML
@FXRedirect //redirect to success page with param
public FXRedirectParam redirectToSuccessWithParam() {
FXRedirectParam params = new FXRedirectParam("SuccessController");
params.addParam("username", usernameTF.getText());
params.addParam("password", passwordPF.getText());
return params;
}
@FXML
@FXRedirect //redirect to success page with query and param
public FXRedirectParam redirectToSuccessWithAll() {
FXRedirectParam params = new FXRedirectParam("SuccessController");
params.addParam("username", usernameTF.getText());
params.addParam("password", passwordPF.getText());
params.addQuery("token", new Date().toString());
return params;
}
}
```
3. Design the Controller which will be redirected to.
@@ -513,8 +571,10 @@ The JavaFX-Plus stipulates that if we need an annotated with `@FXRedirect` metho
public class RegisterController extends FXBaseController {
@FXML
private TextField usernameTF;
@FXML
private TextField emailTF;
@FXML
private PasswordField passwordPF;
@@ -523,7 +583,14 @@ The JavaFX-Plus stipulates that if we need an annotated with `@FXRedirect` metho
@FXML
public void registerClick() {
if (validate()) { //validate(): validate that if a user can register
UserEntity userEntity = new UserEntity();
userEntity.setUsername(usernameTF.getText());
userEntity.setPassword(passwordPF.getText());
userEntity.setEmail(emailTF.getText());
// TODO register
redirectToRegisterSuccess(userEntity);
}
}
@FXML
@@ -535,6 +602,13 @@ The JavaFX-Plus stipulates that if we need an annotated with `@FXRedirect` metho
public String redirectToLogin() {
return "LoginController";
}
@FXRedirect
public FXRedirectParam redirectToRegisterSuccess(UserEntity userEntity) {
FXRedirectParam fxRedirectParam = new FXRedirectParam("SuccessController");
fxRedirectParam.addParam("user", userEntity);
return fxRedirectParam;
}
}
```
@@ -545,7 +619,52 @@ The JavaFX-Plus stipulates that if we need an annotated with `@FXRedirect` metho
}
```
4. When we redirect to another controller, we need to process the data. We can override the method of `beforeShowStage` in FXBaseController, which will be revoked before the revoke of `showStage()`. FXBaseController includes `query` and `param` fields, which storage the transformed data in the redirection.
```java
@FXController(path = "redirectDemo/success.fxml")
@FXWindow(title = "success")
public class SuccessController extends FXBaseController implements Initializable {
@FXML
private Label title;
@FXML
private Label usernameLabel;
@FXML
private Label passwordLabel;
@FXML
private Label tokenLabel;
@FXML
@FXRedirect
public String redirectToLogin() {
return "LoginController";
}
@Override
public void beforeShowStage() {
if (this.getQuery().get("showType") != null) {
String showType = (String) this.getQuery().get("showType");
if (showType.equals("1")) { //register
title.setText("Register Success");
if (this.getParam().get("user") != null) {
UserEntity userEntity = (UserEntity) this.getParam().get("user");
usernameLabel.setText(userEntity.getUsername());
passwordLabel.setText(userEntity.getPassword());
}
} else { //login ,username and password will be transformed with param
title.setText("Login Success");
if (this.getParam().size() > 1) {
usernameLabel.setText(String.valueOf(this.getParam().get("username")));
passwordLabel.setText(String.valueOf(this.getParam().get("password")));
}
}
}
}
}
```
#### Example Code
@@ -557,11 +676,13 @@ The example code is stored at `cn.edu.scau.biubiusuisui.example.redirectDemo`, a
2. popup an window as a dialog(do not close the current window)
![20191208-125511-not close](README.en/20191208-125511-not_close.gif)
![20191208-125511-not close](README.en/redirectDemo/20191208-125511-not_close.gif)
3. redirect to another window with data
![redirect_with_data](README.en/redirect_with_data_en.gif)
#### Deficiencies
Currently, the JavaFX-Plus does not support the redirection to windows with data, but support redrecting to another window with nothing.
## How to Use JavaFX-Plus
@@ -577,7 +698,7 @@ Currently, the JavaFX-Plus does not support the redirection to windows with data
| @FXField | to mark a field in java bean marked by @FXEntity to be reflected to Property type | | |
| @FXSender | to mark a method as sending signal method | name | not necessary, renames the signal |
| @FXReceiver | to mark a method as receiving signal method | name | necessary, marks the subscribed signal |
| @FXRedirect | to mark a method that can redirect to anthor window | close | not necessary, the boolean value marks if close current window; the return value of this method should be the name of redrecting Controller |
| @FXRedirect | to mark a method that can redirect to anthor window | close | not necessary, the boolean value marks if close current window; the return value of this method should be the name of redrecting Controller or FXRedirectParam class. |
### Two Factories and A Context

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 MiB

148
README.md
View File

@@ -40,7 +40,6 @@
- [规定](#规定)
- [使用方法](#使用方法)
- [示例演示](#示例演示)
- [不足之处](#不足之处)
[框架的使用](#框架的使用)
@@ -199,7 +198,6 @@ public class MainController extends FXBaseController {
*/
@FXReceiver(name = "TopBarController:sendToMain")
public void handleTopBar(String msg) {
// TODO: 2019/12/8
// 处理导航栏的点击事件
outTA.appendText(msg + "\n");
}
@@ -474,7 +472,7 @@ public class MainController extends FXBaseController implements Initializable {
#### 规定
本框架规定,当需要使用`@FXRedirect`标记函数处理重定向时函数必须是返回String类型的函数且返回已注册的Controller名如需要重定向至登录成功界面控制器为`SuccessController`,则需要写上`return "SuccessController"。
本框架规定,当需要使用`@FXRedirect`标记函数处理重定向时,函数必须是返回`String``FXRedirectParam`类型的函数,均需要提供已注册的Controller名如需要重定向至登录成功界面,控制器为`SuccessController`,则需要写上`return "SuccessController"`此时并未携带相关数据如需携带数据可使用返回URL的方式或返回`FXRedirectParam`,参考以下用法
#### 使用方法
@@ -491,44 +489,101 @@ public class MainController extends FXBaseController implements Initializable {
public String redirectToDialog() {
return "DialogController";
}
@FXML
@FXRedirect //登录成功 Query方式
public String redirectToSuccessWithQuery() {
return "SuccessController?username=" + usernameTF.getText();
}
@FXML
@FXRedirect //登录成功 Param方式
public FXRedirectParam redirectToSuccessWithParam() {
FXRedirectParam params = new FXRedirectParam("SuccessController"); //需要跳转至Controller的名称
params.addParam("username", usernameTF.getText());
return params;
}
@FXML
@FXRedirect //登录成功 两种方式混合
public FXRedirectParam redirectToSuccessWithAll() {
FXRedirectParam params = new FXRedirectParam("SuccessController"); //需要跳转至Controller的名称
params.addParam("username", usernameTF.getText());
params.addQuery("token", new Date().toString());
return params;
}
```
close是标明是否需要关闭当前的窗口默认为true即默认当跳转另一个窗口时关闭当前窗口。
如果需要携带数据跳转至另一窗口可选择使用返回URL字符串`return "SuccessController?name=JavaFX&password=Plus"`的形式或返回JavaFX-Plus提供的`FXRedirectParam`类根据数据传递方式选择addParam()或addQuery()两种方式进行添加参数数据操作。
2. 创建程序初始界面Controller此处举例为登录界面
首先我们设计LoginController和SuccessController之间的数据接口如下
```java
username: 用户名
password: 用户密码
token: 令牌 //设计用于两种方式传递数据
```
代码如下:
```java
@FXController(path = "redirectDemo/login.fxml")
@FXWindow(title = "redirectDemo", mainStage = true)
public class LoginController extends FXBaseController {
@FXML
private TextField usernameTF;
@FXML
private PasswordField passwordPF;
@FXML
public void registerClick() {
System.out.println("点击注册.....");
public void registerClick() { //点击“注册”
redirectToRegister();
}
@FXRedirect
public String redirectToRegister() {
public String redirectToRegister() { //重定向至注册界面
return "RegisterController";
}
@FXML
@FXRedirect(close = false) //测试弹窗
@FXRedirect(close = false) //弹窗
public String redirectToDialog() {
return "DialogController";
}
@FXML
@FXRedirect //登录成功 Query方式
public String redirectToSuccessWithQuery() {
return "SuccessController?username=" + usernameTF.getText() + "&password=" + passwordPF.getText();
}
@FXML
@FXRedirect //登录成功 Param方式
public FXRedirectParam redirectToSuccessWithParam() {
FXRedirectParam params = new FXRedirectParam("SuccessController");
params.addParam("username", usernameTF.getText());
params.addParam("password", passwordPF.getText());
return params;
}
@FXML
@FXRedirect
public FXRedirectParam redirectToSuccessWithAll() {
FXRedirectParam params = new FXRedirectParam("SuccessController");
params.addParam("username", usernameTF.getText());
params.addParam("password", passwordPF.getText());
params.addQuery("token", new Date().toString());
return params;
}
}
```
3. 编写需要跳转的界面Controller比如登录时尚无账号跳转至注册界面和测试弹窗的Controller
3. 编写需要跳转的界面Controller比如登录时尚无账号跳转至注册界面(不弹窗)和测试弹窗的Controller
```java
@FXController(path = "redirectDemo/register.fxml")
@@ -536,8 +591,10 @@ public class MainController extends FXBaseController implements Initializable {
public class RegisterController extends FXBaseController {
@FXML
private TextField usernameTF;
@FXML
private TextField emailTF;
@FXML
private PasswordField passwordPF;
@@ -546,7 +603,14 @@ public class MainController extends FXBaseController implements Initializable {
@FXML
public void registerClick() {
if (validate()) { //validate()为校验能否注册函数
UserEntity userEntity = new UserEntity();
userEntity.setUsername(usernameTF.getText());
userEntity.setPassword(passwordPF.getText());
userEntity.setEmail(emailTF.getText());
// TODO 注册操作
redirectToRegisterSuccess(userEntity);
}
}
@FXML
@@ -558,6 +622,13 @@ public class MainController extends FXBaseController implements Initializable {
public String redirectToLogin() {
return "LoginController";
}
@FXRedirect
public FXRedirectParam redirectToRegisterSuccess(UserEntity userEntity) {
FXRedirectParam fxRedirectParam = new FXRedirectParam("SuccessController");
fxRedirectParam.addParam("user", userEntity);
return fxRedirectParam;
}
}
```
@@ -568,7 +639,52 @@ public class MainController extends FXBaseController implements Initializable {
}
```
4. 在携带数据跳转至另一Controller后需要对传入数据进行处理此时需要重写FXBaseController中的`beforeShowStage()`函数此函数将在某一Controller的`showStage()`之前执行即在Controller显示之前进行处理数据等相关操作。FXBaseController中包含`query`和`param`两个属性,用于存储重定向中的传递数据。
```java
@FXController(path = "redirectDemo/success.fxml")
@FXWindow(title = "success")
public class SuccessController extends FXBaseController implements Initializable {
@FXML
private Label title;
@FXML
private Label usernameLabel;
@FXML
private Label passwordLabel;
@FXML
private Label tokenLabel;
@FXML
@FXRedirect
public String redirectToLogin() {
return "LoginController";
}
@Override
public void beforeShowStage() {
if (this.getQuery().get("showType") != null) {
String showType = (String) this.getQuery().get("showType");
if (showType.equals("1")) { //注册
title.setText("注册成功");
if (this.getParam().get("user") != null) {
UserEntity userEntity = (UserEntity) this.getParam().get("user");
usernameLabel.setText(userEntity.getUsername());
passwordLabel.setText(userEntity.getPassword());
}
} else { //登录 ,登录时username和password以param方式传递
title.setText("登录成功");
if (this.getParam().size() > 1) {
usernameLabel.setText(String.valueOf(this.getParam().get("username")));
passwordLabel.setText(String.valueOf(this.getParam().get("password")));
}
}
}
}
}
```
#### 示例演示
@@ -582,9 +698,11 @@ public class MainController extends FXBaseController implements Initializable {
![20191208-125511-not close](README/redirectDemo/20191208-125511-not_close.gif)
#### 不足之处
3. 携带数据跳转窗口
![redirect_with_data](README/redirect_with_data.gif)
暂未实现携带数据的窗口跳转目前只实现纯粹跳转到另一个Controller。
@@ -592,7 +710,7 @@ public class MainController extends FXBaseController implements Initializable {
### 内置注解
| 名字 | 作用 | 参数 | 备注 |
| ------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ---------------------------------------- |
| ------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| @FXData | 标明这个普通bean要装配成javafxBean | fx_id | 重新命名 |
| @FXScan | 扫描@FXEntity和@FXController注解标记的类 | 要扫描的目录 | 默认值是当前目录之下所有 |
| @FXController | 标记这个类为控件 | pathfxml文件地址 | 无 |
@@ -601,7 +719,7 @@ public class MainController extends FXBaseController implements Initializable {
| @FXField | 代表这个属性要映射为Property属性 | | |
| @FXSender | 信号发送者 | name重命名信号 | |
| @FXReceiver | 信号接收函数 | name订阅的发射者函数名 | 不可空 |
| @FXRedirect | 标记函数为重定向函数 | close是否关闭当前窗口 | 返回值为某个使用了FXView注解的Controller |
| @FXRedirect | 标记函数为重定向函数 | close是否关闭当前窗口 | 返回值为某个使用了FXView注解的Controller名或JavaFX-Plus提供的FXRedirectParam类 |
### 两个工厂和一个context

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 MiB

View File

@@ -7,7 +7,6 @@ import cn.edu.scau.biubiusuisui.factory.FXBuilder;
import cn.edu.scau.biubiusuisui.factory.FXControllerFactory;
import cn.edu.scau.biubiusuisui.function.FXWindowParser;
import cn.edu.scau.biubiusuisui.utils.ClassUtils;
import javafx.application.Application;
import java.lang.annotation.Annotation;
import java.util.HashSet;
@@ -22,7 +21,7 @@ public class FXPlusApplication {
private static FXWindowParser windowAnnotationParser = new FXWindowParser();
private static BeanBuilder DEFALUT_BEAN_FACTORY = new FXBuilder();
private static BeanBuilder DEFAULT_BEAN_FACTORY = new FXBuilder();
private static BeanBuilder beanBuilder;
@@ -56,7 +55,7 @@ public class FXPlusApplication {
}
public static void start(Class clazz) {
start(clazz, DEFALUT_BEAN_FACTORY);
start(clazz, DEFAULT_BEAN_FACTORY);
}
private static void loadFXPlusClass(String className, BeanBuilder beanBuilder) throws ClassNotFoundException {

View File

@@ -4,12 +4,16 @@ import cn.edu.scau.biubiusuisui.annotation.FXController;
import cn.edu.scau.biubiusuisui.annotation.FXWindow;
import cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus;
import cn.edu.scau.biubiusuisui.config.FXPlusApplication;
import cn.edu.scau.biubiusuisui.exception.NotFXWindowException;
import cn.edu.scau.biubiusuisui.utils.StringUtils;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Map;
/**
* @Author jack
@@ -31,6 +35,14 @@ public class FXBaseController extends Pane {
private boolean isController = false;
private boolean isWindow = false;
/**
* @Author: yangsuiyu
* @Descriptions: 用于携带信息数据
*/
private Map<String, Object> query = new HashMap<>();
private Map<String, Object> param = new HashMap<>();
public FXBaseController(String name) {
this.name = name;
}
@@ -40,6 +52,7 @@ public class FXBaseController extends Pane {
Annotation[] annotations = getClass().getAnnotations();
// Find FXController cn.edu.scau.biubiusuisui.annotation
for (Annotation annotation : annotations) {
// 是否Controller
if (annotation.annotationType().equals(FXController.class)) {
fxController = (FXController) annotation;
isController = true;
@@ -55,7 +68,6 @@ public class FXBaseController extends Pane {
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
fxmlLoader.setShow(true);
// System.out.println("?");
try {
fxmlLoader.load();
} catch (IOException e) {
@@ -68,12 +80,21 @@ public class FXBaseController extends Pane {
}
/**
* 在显示Stage之前的操作
*/
public void beforeShowStage() {
}
/**
* 唤起舞台
*/
public void showStage() {
this.beforeShowStage();
if (isWindow) {
this.stage.show();
}
}
@@ -86,6 +107,13 @@ public class FXBaseController extends Pane {
}
}
public void showAndWait() {
this.beforeShowStage();
if (isWindow) {
this.stage.showAndWait();
}
}
public String getName() {
if ("".equals(name) || name == null) { // 原本无“name == null”判断条件会出错
return StringUtils.getBaseClassName(getClass().getSimpleName());
@@ -122,4 +150,19 @@ public class FXBaseController extends Pane {
this.stage = stage;
}
public Map<String, Object> getQuery() {
return query;
}
public Map<String, Object> getParam() {
return param;
}
public void setQuery(Map<String, Object> query) {
this.query = query;
}
public void setParam(Map<String, Object> param) {
this.param = param;
}
}

View File

@@ -25,7 +25,7 @@ public class FXPlusContext {
private static Map<Object, FXEntityProxy> beanMap = new ConcurrentHashMap<>(); // Object注册为FXEntityObject
public static void addController(FXBaseController fxBaseController) {
public static void registerController(FXBaseController fxBaseController) {
List<FXBaseController> controllers = controllerContext.get(fxBaseController.getName());
if (controllers == null) {
controllers = new LinkedList<>();
@@ -33,9 +33,6 @@ public class FXPlusContext {
controllers.add(fxBaseController);
}
public static List<FXBaseController> getControllers(String key) {
return controllerContext.get(key);
}
public static FXEntityProxy getProxyByBeanObject(Object object) {
return beanMap.get(object);
@@ -45,6 +42,10 @@ public class FXPlusContext {
beanMap.put(object, fxEntityProxy);
}
public static List<FXBaseController> getControllers(String key) {
return controllerContext.get(key);
}
public static Property getEntityPropertyByName(Object object, String fieldName) {
return getProxyByBeanObject(object).getPropertyByFieldName(fieldName);
}

View File

@@ -0,0 +1,53 @@
package cn.edu.scau.biubiusuisui.entity;
import java.util.HashMap;
import java.util.Map;
/**
* @author suiyu_yang
* @description 跳转窗口携带的参数
* @date 2020/4/6 18:06
* @email suiyu_yang@163.com
*/
public class FXRedirectParam {
private String toController;
private Map<String, Object> query = new HashMap<>();
private Map<String, Object> params = new HashMap<>();
public FXRedirectParam(String toController) {
this.toController = toController;
}
public String getToController() {
return toController;
}
public void setToController(String toController) {
this.toController = toController;
}
public Map<String, Object> getParams() {
return params;
}
public Map<String, Object> getQueryMap() {
return query;
}
public void addParam(String key, Object param) {
this.params.put(key, param);
}
public Object getParam(String key) {
return this.params.get(key);
}
public void addQuery(String key, Object param) {
this.query.put(key, param);
}
public Object getOneQuery(String key) {
return this.query.get(key);
}
}

View File

@@ -2,16 +2,13 @@ package cn.edu.scau.biubiusuisui.example.bindDemo;
import cn.edu.scau.biubiusuisui.annotation.FXBind;
import cn.edu.scau.biubiusuisui.annotation.FXController;
import cn.edu.scau.biubiusuisui.annotation.FXData;
import cn.edu.scau.biubiusuisui.annotation.FXWindow;
import cn.edu.scau.biubiusuisui.entity.FXBaseController;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.control.*;
import java.net.URL;
import java.util.ResourceBundle;
@@ -38,18 +35,34 @@ public class MainController extends FXBaseController implements Initializable {
@FXML
private Label userPswLabel;
@FXML
private Label ageLabel;
@FXML
private Label enableLabel;
@FXML
private TextField usernameTF;
@FXML
private PasswordField pswPF;
@FXData
@FXBind({
"name=${usernameTF.text}",
"password=${pswPF.text}"
})
private User user = new User();
@FXML
private TextField ageTF;
@FXML
private ToggleGroup enableButtons;
//
// @FXData
// @FXBind({
// "name=${usernameTF.text}",
// "password=${pswPF.text}",
// "age=${ageTF.text}",
// "isEnable=${enableButtons.getSelectedToggle().getUserData()}"
// })
// private User user = new User();
private UserPropertyEntity user = new UserPropertyEntity();
// View bind to Expression
@FXML
@@ -67,10 +80,29 @@ public class MainController extends FXBaseController implements Initializable {
@FXBind("text=${@toUk(money.text)}")
private Label uk;
@Override
public void initialize(URL location, ResourceBundle resources) {
money.setText("0");
money.textProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
if (null == newValue || "".equals(newValue)) {
money.setText("0");
} else if (!newValue.matches("^[0-9]*$")) {
money.setText(oldValue);
}
}
});
}
@FXML
public void clickToShowInfo() {
RadioButton button = (RadioButton) enableButtons.getSelectedToggle();
System.out.println(button.getText());
usernameLabel.setText(user.getName());
userPswLabel.setText(user.getPassword());
ageLabel.setText(Integer.toString(user.getAge()));
enableLabel.setText(Boolean.toString(user.getEnable()));
}
public String toUs(String value) {
@@ -91,18 +123,4 @@ public class MainController extends FXBaseController implements Initializable {
return String.valueOf(money * percent);
}
@Override
public void initialize(URL location, ResourceBundle resources) {
money.setText("0");
money.textProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
if (null == newValue || "".equals(newValue)) {
money.setText("0");
} else if (!newValue.matches("^[0-9]*$")) {
money.setText(oldValue);
}
}
});
}
}

View File

@@ -0,0 +1,37 @@
package cn.edu.scau.biubiusuisui.example.bindDemo;
/**
* @author suiyu_yang
* @description 详细信息
* @date 2020/4/6 00:29
* @email suiyu_yang@163.com
*/
public class Profile {
private String birthday;
private String address;
private String avatar;
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getAvatar() {
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
}

View File

@@ -3,9 +3,11 @@ package cn.edu.scau.biubiusuisui.example.bindDemo;
import cn.edu.scau.biubiusuisui.annotation.FXEntity;
import cn.edu.scau.biubiusuisui.annotation.FXField;
import java.util.List;
/**
* @Author jack
* @Date:2019/7/27 12:19
* @Author yangsuiyu
* @Date:2020/4/5 12:19
*/
@FXEntity
public class User {
@@ -13,6 +15,16 @@ public class User {
private String name;
@FXField
private String password;
@FXField
private Integer age;
@FXField
private List<Double> scores;
@FXField
private Double gpa;//平均分
@FXField
private Profile profile;
@FXField
private boolean isEnable;
public String getName() {
return name;
@@ -29,4 +41,46 @@ public class User {
public void setPassword(String password) {
this.password = password;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public List<Double> getScores() {
return scores;
}
public void addScore(double score) {
this.scores.add(score);
}
public Profile getProfile() {
return profile;
}
public void setProfile(Profile profile) {
this.profile = profile;
}
public boolean isEnable() {
return isEnable;
}
public void setEnable(boolean enable) {
isEnable = enable;
}
public double getGpa() {
double sum = 0;
for (double score : scores) {
sum += score;
}
gpa = sum / scores.size();
return gpa;
}
}

View File

@@ -0,0 +1,104 @@
package cn.edu.scau.biubiusuisui.example.bindDemo;
import javafx.beans.property.*;
import javafx.collections.ObservableList;
/**
* @author suiyu_yang
* @description User的JavaFXBean
* @date 2020/4/6 14:30
* @email suiyu_yang@163.com
*/
public class UserPropertyEntity {
private SimpleStringProperty name;
private SimpleStringProperty password;
private SimpleIntegerProperty age;
private SimpleListProperty<Double> scores;
private SimpleDoubleProperty gpa;//平均分
private SimpleObjectProperty<Profile> profile;
private SimpleBooleanProperty enable;
public String getName() {
return name.get();
}
public SimpleStringProperty nameProperty() {
return name;
}
public void setName(String name) {
this.name.set(name);
}
public String getPassword() {
return password.get();
}
public SimpleStringProperty passwordProperty() {
return password;
}
public void setPassword(String password) {
this.password.set(password);
}
public int getAge() {
return age.get();
}
public SimpleIntegerProperty ageProperty() {
return age;
}
public void setAge(int age) {
this.age.set(age);
}
public ObservableList<Double> getScores() {
return scores.get();
}
public SimpleListProperty<Double> scoresProperty() {
return scores;
}
public void setScores(ObservableList<Double> scores) {
this.scores.set(scores);
}
public double getGpa() {
return gpa.get();
}
public SimpleDoubleProperty gpaProperty() {
return gpa;
}
public void setGpa(double gpa) {
this.gpa.set(gpa);
}
public Profile getProfile() {
return profile.get();
}
public SimpleObjectProperty<Profile> profileProperty() {
return profile;
}
public void setProfile(Profile profile) {
this.profile.set(profile);
}
public boolean getEnable() {
return enable.get();
}
public SimpleBooleanProperty enableProperty() {
return enable;
}
public void setEnable(boolean enable) {
this.enable.set(enable);
}
}

View File

@@ -10,9 +10,9 @@ import javafx.stage.Stage;
* @Date:2019/7/27 1:43
*/
@FXScan(base = "cn.edu.scau.biubiusuisui.example.listDemo")
public class Demo extends Application {
public class ListDemo extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
FXPlusApplication.start(Demo.class);
FXPlusApplication.start(ListDemo.class);
}
}

View File

@@ -11,6 +11,7 @@ import javafx.fxml.FXML;
import javafx.scene.control.ListView;
import java.util.ArrayList;
import java.util.List;
/**
* @Author jack
@@ -35,7 +36,7 @@ public class MainController extends FXBaseController {
user.addNames("Jack\t" + (count++));
}
public ObservableList toList(ArrayList list) {
public ObservableList toList(List list) {
if (list == null) {
return null;
}

View File

@@ -4,6 +4,7 @@ import cn.edu.scau.biubiusuisui.annotation.FXEntity;
import cn.edu.scau.biubiusuisui.annotation.FXField;
import java.util.ArrayList;
import java.util.List;
/**
* @Author jack
@@ -18,7 +19,7 @@ public class User {
private String password;
@FXField
private ArrayList<String> names = new ArrayList<>();
private List<String> names = new ArrayList<>();
public User() {
@@ -47,7 +48,7 @@ public class User {
this.password = password;
}
public ArrayList<String> getNames() {
public List<String> getNames() {
return names;
}

View File

@@ -28,7 +28,6 @@ public class MainController extends FXBaseController {
*/
@FXReceiver(name = "TopBarController:sendToMain")
public void handleTopBar(String msg) {
// TODO: 2019/12/8
// 处理导航栏的点击事件
outTA.appendText(msg + "\n");
}

View File

@@ -4,10 +4,15 @@ import cn.edu.scau.biubiusuisui.annotation.FXController;
import cn.edu.scau.biubiusuisui.annotation.FXRedirect;
import cn.edu.scau.biubiusuisui.annotation.FXWindow;
import cn.edu.scau.biubiusuisui.entity.FXBaseController;
import cn.edu.scau.biubiusuisui.entity.FXRedirectParam;
import javafx.fxml.FXML;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @author suiyu_yang
* @description
@@ -41,9 +46,30 @@ public class LoginController extends FXBaseController {
}
@FXML
@FXRedirect //登录成功
public String redirectToSuccess() {
@FXRedirect //登录成功 Query方式
public String redirectToSuccessWithQuery() {
return "SuccessController?showType=0&username=" + usernameTF.getText() + "&password=" + passwordPF.getText();
}
return "SuccessController";
@FXML
@FXRedirect //登录成功 Param方式
public FXRedirectParam redirectToSuccessWithParam() {
FXRedirectParam params = new FXRedirectParam("SuccessController");
params.addParam("username", usernameTF.getText());
params.addParam("password", passwordPF.getText());
params.addQuery("showType", "0");
return params;
}
@FXML
@FXRedirect
public FXRedirectParam redirectToSuccessWithAll() {
FXRedirectParam params = new FXRedirectParam("SuccessController");
params.addParam("username", usernameTF.getText());
params.addParam("password", passwordPF.getText());
params.addQuery("token", new Date().toString());
params.addQuery("showType", "0");
return params;
}
}

View File

@@ -4,6 +4,7 @@ import cn.edu.scau.biubiusuisui.annotation.FXController;
import cn.edu.scau.biubiusuisui.annotation.FXRedirect;
import cn.edu.scau.biubiusuisui.annotation.FXWindow;
import cn.edu.scau.biubiusuisui.entity.FXBaseController;
import cn.edu.scau.biubiusuisui.entity.FXRedirectParam;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.PasswordField;
@@ -23,6 +24,7 @@ public class RegisterController extends FXBaseController {
@FXML
private TextField emailTF;
@FXML
private PasswordField passwordPF;
@@ -36,8 +38,8 @@ public class RegisterController extends FXBaseController {
userEntity.setUsername(usernameTF.getText());
userEntity.setPassword(passwordPF.getText());
userEntity.setEmail(emailTF.getText());
redirectToRegisterSuccess(userEntity);
}
}
@FXML
@@ -50,6 +52,13 @@ public class RegisterController extends FXBaseController {
return "LoginController";
}
@FXRedirect
public FXRedirectParam redirectToRegisterSuccess(UserEntity userEntity) {
FXRedirectParam fxRedirectParam = new FXRedirectParam("SuccessController");
fxRedirectParam.addQuery("showType", "1");
fxRedirectParam.addParam("user", userEntity);
return fxRedirectParam;
}
// 校验
private boolean validate() {

View File

@@ -4,6 +4,7 @@ import cn.edu.scau.biubiusuisui.annotation.FXController;
import cn.edu.scau.biubiusuisui.annotation.FXRedirect;
import cn.edu.scau.biubiusuisui.annotation.FXWindow;
import cn.edu.scau.biubiusuisui.entity.FXBaseController;
import cn.edu.scau.biubiusuisui.exception.NotFXWindowException;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
@@ -21,12 +22,17 @@ import java.util.ResourceBundle;
@FXWindow(title = "success")
public class SuccessController extends FXBaseController implements Initializable {
@FXML
private Label title;
@FXML
private Label usernameLabel;
@FXML
private Label passwordLabel;
@FXML
private Label tokenLabel;
@FXML
@FXRedirect
@@ -34,9 +40,35 @@ public class SuccessController extends FXBaseController implements Initializable
return "LoginController";
}
@Override
public void beforeShowStage() {
if (this.getQuery().get("showType") != null) {
String showType = (String) this.getQuery().get("showType");
if (showType.equals("1")) { //注册
title.setText("注册成功");
if (this.getParam().get("user") != null) {
UserEntity userEntity = (UserEntity) this.getParam().get("user");
usernameLabel.setText(userEntity.getUsername());
passwordLabel.setText(userEntity.getPassword());
}
} else { //登录
title.setText("登录成功");
// 此处为演示多种方式数据传递才进行多次赋值实际应用时应根据数据API进行相应的数据获取操作
if (this.getQuery().size() > 1) { //query方式传递
usernameLabel.setText(String.valueOf(this.getQuery().get("username")));
passwordLabel.setText(String.valueOf(this.getQuery().get("password")));
tokenLabel.setText(String.valueOf(this.getQuery().get("token")));
}
if (this.getParam().size() > 1) { //param方式传递
usernameLabel.setText(String.valueOf(this.getParam().get("username")));
passwordLabel.setText(String.valueOf(this.getParam().get("password")));
}
}
}
}
@Override
public void initialize(URL location, ResourceBundle resources) {
}
}

View File

@@ -0,0 +1,13 @@
package cn.edu.scau.biubiusuisui.exception;
/**
* @author suiyu_yang
* @description 不合法URL
* @date 2020/4/6 15:59
* @email suiyu_yang@163.com
*/
public class InvalidURLException extends Exception {
public InvalidURLException() {
super("the url is invalid");
}
}

View File

@@ -0,0 +1,13 @@
package cn.edu.scau.biubiusuisui.exception;
/**
* @author suiyu_yang
* @description 某Controller不是窗口
* @date 2020/4/6 17:10
* @email suiyu_yang@163.com
*/
public class NotFXWindowException extends Exception {
public NotFXWindowException() {
super("the controller is not a window");
}
}

View File

@@ -13,5 +13,4 @@ public class ChangeParser implements BindParser {
}
}

View File

@@ -5,13 +5,11 @@ import cn.edu.scau.biubiusuisui.annotation.FXValue;
import cn.edu.scau.biubiusuisui.exception.NoSuchChangeMethod;
import com.sun.istack.internal.NotNull;
import com.sun.javafx.fxml.expression.Expression;
import com.sun.javafx.fxml.expression.VariableExpression;
import javafx.beans.property.Property;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.NoSuchElementException;
/**
* 将FXBind中表达式建立绑定
@@ -24,7 +22,7 @@ import java.util.NoSuchElementException;
* expression -> bean.field
* <p>
* FXBind("text=${bean.field})
* textProperty 通过 adapter.getModelProeprty --> textProperty实例
* textProperty 通过 adapter.getModelProperty --> textProperty实例
* bean 通过namespace 获取因为bean有FXEntity标签所以返回包装过后的bean的property
* 最后
* left.bind(right)
@@ -60,7 +58,7 @@ public class ExpressionParser {
private static final String FUNCTION_PREFIX = "@";
private MyExpressionValue getRightExpreesion(MyBeanAdapter myBeanAdapter, String key, String rightExpression) {
private MyExpressionValue getRightExpression(MyBeanAdapter myBeanAdapter, String key, String rightExpression) {
Expression expression = null;
if (rightExpression.startsWith(FUNCTION_PREFIX)) {
expression = getFunctionExpression(rightExpression);
@@ -82,20 +80,20 @@ public class ExpressionParser {
if (!"".equals(argString.trim())) {
args = argString.split(",");
}
Class clazz = targetController.getClass();
Method[] methods = clazz.getMethods();
Expression[] expressions = null;
Class targetClazz = targetController.getClass();
Method[] methods = targetClazz.getMethods();
Expression[] expressionArgs = null;
if (args != null) {
expressions = new Expression[args.length];
expressionArgs = new Expression[args.length];
for (int i = 0; i < args.length; i++) {
if (!"".equals(args[i].trim())) {
expressions[i] = Expression.valueOf(args[i]);
expressionArgs[i] = Expression.valueOf(args[i]);
}
}
}
for (Method method : methods) {
if (method.getName().equals(methodName)) {
expression = new FunctionExpression(method, targetController, expressions);
expression = new FunctionExpression(method, targetController, expressionArgs);
}
}
return expression;
@@ -120,7 +118,7 @@ public class ExpressionParser {
ExpressionType expressionType;
if (right.startsWith(BIND_PREFIX) && right.endsWith(BIND_SUFIX)) {
int length = right.length();
right = right.substring(2, length - 1);
right = right.substring(2, length - 1); //已经去掉“${”的表达式
expressionType = ExpressionType.DataExpression;
} else {
right = right.substring(1); //#changeMethod -> changeMethod
@@ -133,12 +131,16 @@ public class ExpressionParser {
bindDataExpression(left, right, myBeanAdapter, leftProperty);
break;
case ActionExpression:
//
bindActionExpression(right, leftProperty);
}
}
/**
* @param right
* @param leftProperty
* @throws NoSuchChangeMethod
* @Description 鼠标事件或键盘事件绑定
*/
private void bindActionExpression(String right, Property leftProperty) throws NoSuchChangeMethod {
Class clazz = targetController.getClass();
Method[] methods = clazz.getMethods();
@@ -158,8 +160,15 @@ public class ExpressionParser {
}
}
/**
* @param left
* @param right
* @param myBeanAdapter
* @param leftProperty
* @Description 数据绑定
*/
private void bindDataExpression(String left, String right, MyBeanAdapter myBeanAdapter, Property leftProperty) {
MyExpressionValue rightProperty = getRightExpreesion(myBeanAdapter, left, right);
MyExpressionValue rightProperty = getRightExpression(myBeanAdapter, left, right);
leftProperty.bind(rightProperty);
}

View File

@@ -28,7 +28,6 @@ import java.net.URL;
*/
public class FXControllerFactory {
private static final BeanBuilder BEAN_BUILDER = new FXBuilder();
private static FXWindowParser fxWindowAnnotationParser = new FXWindowParser();
@@ -136,18 +135,18 @@ public class FXControllerFactory {
* @param fxBaseControllerProxy 代理对象
*/
private static void register(FXBaseController fxBaseController, FXBaseController fxBaseControllerProxy) {
FXPlusContext.addController(fxBaseController); //保存
FXPlusContext.registerController(fxBaseController); //保存
MessageQueue.getInstance().registerConsumer(fxBaseController, fxBaseControllerProxy); // 添加进入消息队列 信号功能
}
/**
* 为有FXWindow注解的类创建Stage
*
* @param fxWindow
* @param clazz
* @param fxBaseControllerProxy
* @return
* @Description 为有FXWindow注解的类创建Stage
*/
private static Stage createWindow(FXWindow fxWindow, FXBaseController fxBaseControllerProxy) {
private static Stage createWindow(FXWindow fxWindow, Class clazz, FXBaseController fxBaseControllerProxy) {
Stage stage = new Stage();
fxBaseControllerProxy.setStage(stage);
double preWidth = fxWindow.preWidth() == 0 ? fxBaseControllerProxy.getPrefWidth() : fxWindow.preWidth();
@@ -156,9 +155,8 @@ public class FXControllerFactory {
stage.setScene(scene);
fxWindowAnnotationParser.parse(stage, fxBaseControllerProxy, fxWindow);
StageManager.getInstance().registerWindow(fxBaseControllerProxy); //注册舞台
StageManager.getInstance().registerWindow(clazz, fxBaseControllerProxy); //注册舞台
if (fxWindow.mainStage() == true) { //当是主舞台时先show为敬
// System.out.println("FXControllerFactory: "+(fxControllerProxy.getStage() == null));
fxBaseControllerProxy.showStage();
}
return stage;
@@ -206,7 +204,7 @@ public class FXControllerFactory {
FXWindow fxWindow = (FXWindow) clazz.getDeclaredAnnotation(FXWindow.class);
if (fxWindow != null) {
FXBaseController fxController = getFXController(clazz, null, BEAN_BUILDER);
return createWindow(fxWindow, fxController);
return createWindow(fxWindow, clazz, fxController);
} else {
return null;
}
@@ -216,7 +214,7 @@ public class FXControllerFactory {
FXWindow fxWindow = (FXWindow) clazz.getDeclaredAnnotation(FXWindow.class);
if (fxWindow != null) {
FXBaseController fxController = getFXController(clazz, null, beanBuilder);
return createWindow(fxWindow, fxController);
return createWindow(fxWindow, clazz, fxController);
} else {
return null;
}
@@ -226,7 +224,7 @@ public class FXControllerFactory {
FXWindow fxWindow = (FXWindow) clazz.getDeclaredAnnotation(FXWindow.class);
if (fxWindow != null) {
FXBaseController fxController = getFXController(clazz, controllerName, BEAN_BUILDER);
return createWindow(fxWindow, fxController);
return createWindow(fxWindow, clazz, fxController);
} else {
return null;
}
@@ -236,7 +234,7 @@ public class FXControllerFactory {
FXWindow fxWindow = (FXWindow) clazz.getDeclaredAnnotation(FXWindow.class);
if (fxWindow != null) {
FXBaseController fxController = getFXController(clazz, controllerName, beanBuilder);
return createWindow(fxWindow, fxController);
return createWindow(fxWindow, clazz, fxController);
} else {
return null;
}

View File

@@ -37,22 +37,33 @@ public class FXEntityFactory {
}
}
/**
* @param object 被转换的对象
* @return
*/
public static Object wrapFXBean(Object object) {
FXEntityProxy fxEntityProxy = new FXEntityProxy();
Object objectProxy = null;
Object proxyObject = null;
try {
objectProxy = fxEntityProxy.getInstance(object); // 初始化代理类
processFXEntityProxyFields(object, objectProxy, fxEntityProxy); //处理FXEntity上的@FXField
FXPlusContext.setProxyByBeanObject(objectProxy, fxEntityProxy);
proxyObject = fxEntityProxy.getInstance(object); // 初始化代理类
processFXEntityProxyFields(object, proxyObject, fxEntityProxy); //处理FXEntity上的@FXField
FXPlusContext.setProxyByBeanObject(proxyObject, fxEntityProxy);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return objectProxy;
return proxyObject;
}
private static void processFXEntityProxyFields(Object entity, Object proxy, FXEntityProxy fxEntityProxy) throws IllegalAccessException {
/**
* @param entityObject 被转换的原Entity对象
* @param proxyObject 被转换对象的FXEntityProxy对象
* @param fxEntityProxy 被转换对象的FXEntityProxy类
* @throws IllegalAccessException
* @Description 处理FXEntity中的FXField注解1. 添加监听 2.赋值FXEntityProxy中的fxFieldWrapperMap
*/
private static void processFXEntityProxyFields(Object entityObject, Object proxyObject, FXEntityProxy fxEntityProxy) throws IllegalAccessException {
Map<String, FXFieldWrapper> fxFieldWrapperMap = new HashMap<>();
Field[] fields = entity.getClass().getDeclaredFields();
Field[] fields = entityObject.getClass().getDeclaredFields();
for (Field field : fields) {
Annotation annotation = ClassUtils.getAnnotationInList(FXField.class, field.getDeclaredAnnotations());
if (annotation != null) {
@@ -60,17 +71,19 @@ public class FXEntityFactory {
field.setAccessible(true);
FXField fxField = (FXField) annotation;
FXFieldWrapper fieldWrapper = new FXFieldWrapper(fxField, field.getType());
if (field.get(entity) == null) {
if (field.get(entityObject) == null) { //没有初始值
property = getFieldDefaultProperty(field);
} else {
property = getFieldProperty(entity, field);
} else { //有初始值
property = getFieldProperty(entityObject, field);
}
if (property != null) {
// 监听
property.addListener((object, oldVal, newVal) -> {
if (!fxField.readOnly()) {
// 判断field.getType()是否为List类型
if (!List.class.isAssignableFrom(field.getType())) {
try {
field.set(proxy, newVal);
field.set(proxyObject, newVal);//赋值
} catch (IllegalAccessException e) {
e.printStackTrace();
}
@@ -78,18 +91,24 @@ public class FXEntityFactory {
}
});
}
// 设置属性
fieldWrapper.setProperty(property);
fxFieldWrapperMap.put(field.getName(), fieldWrapper);
}
}
fxEntityProxy.setFxFieldWrapperMap(fxFieldWrapperMap);
fxEntityProxy.setFXFieldWrapperMap(fxFieldWrapperMap);
}
private static Property getFieldProperty(Object object, Field field) throws IllegalAccessException {
/**
* @param entityObject
* @param field
* @return
* @throws IllegalAccessException
* @Description 某一属性中有初始值时
*/
private static Property getFieldProperty(Object entityObject, Field field) throws IllegalAccessException {
Class type = field.getType();
Object value = field.get(object);
Object value = field.get(entityObject);
Property property = null;
if (Boolean.class.equals(type) || boolean.class.equals(type)) {
@@ -100,7 +119,7 @@ public class FXEntityFactory {
property = new SimpleFloatProperty((Float) value);
} else if (Integer.class.equals(type) || int.class.equals(type)) {
property = new SimpleIntegerProperty((Integer) value);
} else if (Long.class.equals(type) || long.class.equals(property)) {
} else if (Long.class.equals(type) || long.class.equals(type)) {
property = new SimpleLongProperty((Long) value);
} else if (String.class.equals(type)) {
property = new SimpleStringProperty((String) value);
@@ -112,9 +131,16 @@ public class FXEntityFactory {
return property;
}
/**
* @param field
* @return
* @throws IllegalAccessException
* @Description 某一属性中无初始值
*/
private static Property getFieldDefaultProperty(Field field) throws IllegalAccessException {
Class type = field.getType();
Property property = null;
if (Boolean.class.equals(type) || boolean.class.equals(type)) {
property = new SimpleBooleanProperty();
} else if (Double.class.equals(type) || double.class.equals(type)) {
@@ -123,7 +149,7 @@ public class FXEntityFactory {
property = new SimpleFloatProperty();
} else if (Integer.class.equals(type) || int.class.equals(type)) {
property = new SimpleIntegerProperty();
} else if (Long.class.equals(type) || long.class.equals(property)) {
} else if (Long.class.equals(type) || long.class.equals(type)) {
property = new SimpleLongProperty();
} else if (String.class.equals(type)) {
property = new SimpleStringProperty();

View File

@@ -8,6 +8,7 @@ import javafx.stage.Stage;
/**
* @Author jack
* @Date:2019/6/30 10:40
* @Description 解析@FXWindow
*/
public class FXWindowParser {
@@ -15,6 +16,7 @@ public class FXWindowParser {
stage.setTitle(fxWindow.title());
// fxWindow的resizable默认为false
if (fxWindow.resizable()) {
stage.setResizable(true);
}

View File

@@ -33,6 +33,11 @@ public class MessageQueue {
return messageQueue;
}
/**
* @param fxBaseController
* @param fxBaseControllerProxy
* @Description 注册消费者即FXReceiver注解的method
*/
public void registerConsumer(FXBaseController fxBaseController, FXBaseController fxBaseControllerProxy) {
Class clazz = fxBaseController.getClass();
Method[] methods = clazz.getDeclaredMethods();
@@ -54,6 +59,11 @@ public class MessageQueue {
}
}
/**
* @param id
* @param msg
* @Description 处理消息发送id为topic,msg为消息
*/
public void sendMsg(String id, Object msg) {
List<FXMethodEntity> lists = receivers.get(id);
if (lists != null) {
@@ -71,6 +81,7 @@ public class MessageQueue {
}
} else {
try {
// obj the object the underlying method is invoked from
method.invoke(fxBaseController, msg);
} catch (IllegalAccessException e) {
e.printStackTrace();

View File

@@ -28,7 +28,6 @@ public class FXControllerProxy implements MethodInterceptor {
public Object getInstance(FXBaseController target) {
this.target = target;
// System.out.println(target.toString());
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
enhancer.setCallback(this);

View File

@@ -19,6 +19,11 @@ public class FXEntityProxy implements MethodInterceptor {
Object target;
private Map<String, FXFieldWrapper> fxFieldWrapperMap;
/**
* @param target
* @return
* @Desciption 通过getInstance获取代理对象
*/
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
@@ -30,51 +35,53 @@ public class FXEntityProxy implements MethodInterceptor {
/**
* intercept get and set method and
*
* @param o
* @param method
* @param objects
* @param methodProxy
* @param proxy cglib生成的代理对象
* @param method 被代理对象的方法
* @param args 拦截的方法的入参
* @param methodProxy 拦截方法的代理方法
* @return
* @throws Throwable
* @Descripton 拦截getter, setter, del, cls, add方法
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object o1 = methodProxy.invokeSuper(o, objects); //获取该方法运行后的结果
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object revokeResult = methodProxy.invokeSuper(proxy, args); //获取该方法运行后的结果
String methodName = method.getName();
String fieldName = null;
if (methodName.length() >= 3) {
fieldName = StringUtils.toInstanceName(methodName.substring(3)); // 该method有可能是getter和setter方法进行处理
} else {
return o1;
return revokeResult;
}
FXFieldWrapper fxFieldWrapper = fxFieldWrapperMap.get(fieldName);
Property property = getPropertyByFieldName(fieldName);
if (fxFieldWrapper == null || property == null) {
return o1;
if (fxFieldWrapper == null || property == null) { //非属性的getter或setter
return revokeResult;
}
Class type = fxFieldWrapper.getType();
if (methodName.startsWith("set")) {
if (Boolean.class.equals(type) || boolean.class.equals(type)) {
((SimpleBooleanProperty)property).set((Boolean)objects[0]);
((SimpleBooleanProperty) property).set((Boolean) args[0]);
} else if (Double.class.equals(type) || double.class.equals(type)) {
((SimpleDoubleProperty)property).set((Double)objects[0]);
((SimpleDoubleProperty) property).set((Double) args[0]);
} else if (Float.class.equals(type) || float.class.equals(type)) {
((SimpleFloatProperty)property).set((Float) objects[0]);
((SimpleFloatProperty) property).set((Float) args[0]);
} else if (Integer.class.equals(type) || int.class.equals(type)) {
((SimpleIntegerProperty)property).set((Integer) objects[0]);
((SimpleIntegerProperty) property).set((Integer) args[0]);
} else if (Long.class.equals(type) || long.class.equals(type)) {
((SimpleLongProperty)property).set((Long)objects[0]);
((SimpleLongProperty) property).set((Long) args[0]);
} else if (String.class.equals(type)) {
((SimpleStringProperty)property).set((String)objects[0]);
((SimpleStringProperty) property).set((String) args[0]);
}
} else if (methodName.startsWith("add")) {
((SimpleListProperty)(property)).add(objects[0]);
((SimpleListProperty) (property)).add(args[0]);
} else if (methodName.startsWith("del")) {
((SimpleListProperty)(property)).remove(objects[0]);
((SimpleListProperty) (property)).remove(args[0]);
} else if (methodName.startsWith("cls")) {
((SimpleListProperty) (property)).clear();
}
return o1;
return revokeResult;
}
public Object getTarget() {
@@ -92,11 +99,11 @@ public class FXEntityProxy implements MethodInterceptor {
return fxFieldWrapperMap.get(name).getProperty();
}
public Map<String, FXFieldWrapper> getFxFieldWrapperMap() {
public Map<String, FXFieldWrapper> getFXFieldWrapperMap() {
return fxFieldWrapperMap;
}
public void setFxFieldWrapperMap(Map<String, FXFieldWrapper> fxFieldWrapperMap) {
public void setFXFieldWrapperMap(Map<String, FXFieldWrapper> fxFieldWrapperMap) {
this.fxFieldWrapperMap = fxFieldWrapperMap;
}
}

View File

@@ -1,8 +1,13 @@
package cn.edu.scau.biubiusuisui.stage;
import cn.edu.scau.biubiusuisui.entity.FXBaseController;
import cn.edu.scau.biubiusuisui.entity.FXPlusContext;
import cn.edu.scau.biubiusuisui.entity.FXRedirectParam;
import cn.edu.scau.biubiusuisui.exception.InvalidURLException;
import cn.edu.scau.biubiusuisui.factory.FXControllerFactory;
import java.util.ArrayDeque;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -14,8 +19,8 @@ import java.util.concurrent.ConcurrentHashMap;
*/
public class StageManager {
private static StageManager stageManager = null;
private static Map<String, FXBaseController> windows = new ConcurrentHashMap<>(); //
private static Map<String, FXBaseController> initWindows = new ConcurrentHashMap<>();
private static Map<String, Class> windowClazz = new ConcurrentHashMap<>();
/**
* @author yangsuiyu
* @description 1.2新增属性
@@ -38,22 +43,86 @@ public class StageManager {
return stageManager;
}
public void registerWindow(FXBaseController fxBaseControllerProxy) {
if (fxBaseControllerProxy.isWindow()) {
windows.put(fxBaseControllerProxy.getName(), fxBaseControllerProxy);
}
public void registerWindow(Class clazz, FXBaseController fxBaseControllerProxy) {
fxBaseControllerProxy.getClass().getDeclaredAnnotations();
initWindows.put(fxBaseControllerProxy.getName(), fxBaseControllerProxy);
windowClazz.put(fxBaseControllerProxy.getName(), clazz);
}
public void closeStage(String controllerName) {
windows.get(controllerName).closeStage();
if (initWindows.get(controllerName) != null) {
initWindows.get(controllerName).closeStage();
}
}
/**
* 无参数跳转
*
* @param controller
* @param redirectParams
* @Description 跳转
*/
public void redirectTo(Object controller) {
windows.get(controller).showStage();
public void redirectTo(Object redirectParams) {
FXRedirectParam fxRedirectParam = null;
if (redirectParams instanceof String) {
if (((String) redirectParams).contains("?")) { //有参数query return "SuccessController?name=ss&psw=111"
try {
fxRedirectParam = getQueryParamsFromURL((String) redirectParams);
} catch (InvalidURLException e) {
e.printStackTrace();
}
} else { //无参数 return "SuccessController"
fxRedirectParam = new FXRedirectParam((String) redirectParams);
}
} else if (redirectParams instanceof FXRedirectParam) { // return FXRedirectParam
fxRedirectParam = (FXRedirectParam) redirectParams;
}
redirectWithParams(fxRedirectParam);
}
/**
* @param fxRedirectParam
* @Description 携带参数跳转
*/
private void redirectWithParams(FXRedirectParam fxRedirectParam) {
if (fxRedirectParam != null) {
String toControllerStr = fxRedirectParam.getToController();
FXBaseController toController = initWindows.get(toControllerStr);
if (toController != null) {
List<FXBaseController> controllers = FXPlusContext.getControllers(toController.getName());
// if (controllers.size() > 0) {
// FXBaseController newController = controllers.get(controllers.size() - 1);
// toController = FXControllerFactory.getFXController(newController.getClass(), toControllerStr);
//// registerWindow(, toController);
// }
toController.setParam(fxRedirectParam.getParams());
toController.setQuery(fxRedirectParam.getQueryMap());
toController.showStage();
}
}
}
/**
* RedirectController?num=10&name=suisui -> Map:{"num","10"},{"name","suisui"}
*
* @param url
* @return
*/
private FXRedirectParam getQueryParamsFromURL(String url) throws InvalidURLException {
String[] items = url.split("\\?");
if (items.length != 2) {
throw new InvalidURLException();
}
String leftBase = items[0];
String paramsStr = items[1];
String[] paramsKV = paramsStr.split("&");
FXRedirectParam fxRedirectParam = new FXRedirectParam(leftBase);
for (int i = 0; i < paramsKV.length; i++) {
String params[] = paramsKV[i].split("=");
if (params.length != 2) {
throw new InvalidURLException();
} else {
fxRedirectParam.addQuery(params[0], params[1]);
}
}
return fxRedirectParam;
}
}

View File

@@ -7,6 +7,7 @@ import javafx.beans.property.Property;
/**
* @Author jack
* @Date:2019/7/28 1:52
* @Description:
*/
public class BeanUtil {
public static Property getPropertyByName(Object entity, String fieldName) {
@@ -14,6 +15,6 @@ public class BeanUtil {
if (fxEntityProxy == null) {
return null;
}
return fxEntityProxy.getFxFieldWrapperMap().get(fieldName).getProperty();
return fxEntityProxy.getFXFieldWrapperMap().get(fieldName).getProperty();
}
}

View File

@@ -5,9 +5,14 @@ package cn.edu.scau.biubiusuisui.utils;
* @Date:2019/6/25 3:46
*/
import cn.edu.scau.biubiusuisui.exception.InvalidURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
public class StringUtils {
private StringUtils() {
}
@@ -93,4 +98,5 @@ public class StringUtils {
String result = name.substring(0, 1).toUpperCase().concat(name.substring(1));
return result;
}
}

View File

@@ -3,9 +3,11 @@
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.ToggleGroup?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Pane?>
@@ -36,7 +38,7 @@
<content>
<Pane prefHeight="200.0" prefWidth="200.0">
<children>
<VBox layoutX="47.0" layoutY="154.0" prefHeight="143.0" prefWidth="353.0">
<VBox layoutX="47.0" layoutY="154.0" prefHeight="229.0" prefWidth="353.0">
<children>
<HBox alignment="CENTER" prefHeight="60.0" prefWidth="800.0">
<children>
@@ -50,11 +52,29 @@
<PasswordField fx:id="pswPF"/>
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="60.0" prefWidth="800.0">
<children>
<Label prefWidth="40.0" text="年龄"/>
<TextField fx:id="ageTF"/>
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="60.0" prefWidth="353.0" spacing="20.0">
<children>
<Label prefHeight="40.0" text="是否有效"/>
<RadioButton mnemonicParsing="false" text="是">
<toggleGroup>
<ToggleGroup fx:id="enableButtons"/>
</toggleGroup>
</RadioButton>
<RadioButton mnemonicParsing="false" text="否" toggleGroup="$enableButtons"/>
</children>
</HBox>
</children>
</VBox>
<VBox layoutX="381.0" layoutY="124.0" prefHeight="203.0" prefWidth="353.0">
<VBox layoutX="381.0" layoutY="124.0" prefHeight="203.0" prefWidth="353.0" spacing="5.0">
<children>
<Label alignment="CENTER" prefHeight="26.0" prefWidth="359.0" text="输入的用户信息" textAlignment="CENTER">
<Label alignment="CENTER" prefHeight="26.0" prefWidth="359.0" text="输入的用户信息"
textAlignment="CENTER">
<font>
<Font size="20.0"/>
</font>
@@ -71,6 +91,18 @@
<Label fx:id="userPswLabel"/>
</children>
</HBox>
<HBox alignment="CENTER_LEFT" prefHeight="60.0" prefWidth="800.0">
<children>
<Label prefWidth="60.0" text="年龄:"/>
<Label fx:id="ageLabel"/>
</children>
</HBox>
<HBox alignment="CENTER_LEFT" prefHeight="60.0" prefWidth="800.0">
<children>
<Label fx:id="enableLabel" prefWidth="60.0" text="是否有效:"/>
<Label fx:id="userPswLabel2"/>
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
<children>
<Button mnemonicParsing="false" onAction="#clickToShowInfo" text="点击显示"/>

View File

@@ -14,7 +14,7 @@
prefWidth="800.0" type="Pane" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="cn.edu.scau.biubiusuisui.example.redirectDemo.LoginController">
<children>
<VBox alignment="CENTER" layoutX="265.0" layoutY="100.0" prefHeight="300.0" prefWidth="250.0" spacing="10.0">
<VBox alignment="CENTER" prefHeight="356.0" prefWidth="800.0" spacing="10.0">
<children>
<Label alignment="CENTER" prefHeight="50.0" prefWidth="250.0" text="登录">
<font>
@@ -33,7 +33,7 @@
<PasswordField fx:id="passwordPF"/>
</children>
</HBox>
<HBox alignment="CENTER_RIGHT" prefHeight="50.0" prefWidth="200.0">
<HBox alignment="CENTER" prefHeight="50.0" prefWidth="200.0">
<children>
<Label onMouseClicked="#registerClick" prefHeight="50.0" text="还没有账户,去注册" underline="true">
<HBox.margin>
@@ -42,11 +42,20 @@
</Label>
</children>
</HBox>
<HBox alignment="CENTER_RIGHT" prefHeight="50.0" prefWidth="200.0">
<HBox alignment="CENTER" prefHeight="50.0" prefWidth="200.0">
<children>
<VBox alignment="TOP_RIGHT" prefHeight="54.0" prefWidth="167.0" spacing="10.0">
<VBox alignment="CENTER" prefHeight="64.0" prefWidth="810.0" spacing="10.0">
<children>
<Button mnemonicParsing="false" onAction="#redirectToSuccess" text="登录"/>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" spacing="5.0">
<children>
<Button mnemonicParsing="false" onAction="#redirectToSuccessWithQuery"
text="query方式登录"/>
<Button mnemonicParsing="false" onAction="#redirectToSuccessWithParam"
text="param方式登录"/>
<Button mnemonicParsing="false" onAction="#redirectToSuccessWithAll"
text="混合登录"/>
</children>
</HBox>
<Button mnemonicParsing="false" onAction="#redirectToDialog" text="测试弹窗的按钮"/>
</children>
</VBox>

View File

@@ -1,15 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<fx:root maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="500.0"
prefWidth="600.0" type="Pane" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="cn.edu.scau.biubiusuisui.example.redirectDemo.SuccessController">
<children>
<VBox alignment="CENTER" layoutX="158.0" layoutY="80.0" prefHeight="300.0" prefWidth="250.0" spacing="10.0">
<children>
<Label alignment="CENTER" prefHeight="50.0" prefWidth="250.0" text="登录成功">
<Label fx:id="title" alignment="CENTER" prefHeight="50.0" prefWidth="250.0" text="登录成功">
<font>
<Font size="27.0"/>
</font>
@@ -17,13 +21,19 @@
<HBox alignment="CENTER" prefHeight="50.0" prefWidth="200.0">
<children>
<Label alignment="CENTER" prefHeight="50.0" prefWidth="50.0" text="用户名:"/>
<Label fx:id="usernameLabel" alignment="CENTER" prefHeight="50.0" prefWidth="150.0"/>
<Label fx:id="usernameLabel" alignment="CENTER" prefHeight="50.0" prefWidth="203.0"/>
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="50.0" prefWidth="200.0">
<children>
<Label alignment="CENTER" prefHeight="50.0" prefWidth="50.0" text="密码:"/>
<Label fx:id="passwordLabel" alignment="CENTER" prefHeight="50.0" prefWidth="150.0"/>
<Label fx:id="passwordLabel" alignment="CENTER" prefHeight="50.0" prefWidth="205.0"/>
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="50.0" prefWidth="200.0">
<children>
<Label alignment="CENTER" prefHeight="50.0" prefWidth="50.0" text="Token:"/>
<Label fx:id="tokenLabel" alignment="CENTER" prefHeight="50.0" prefWidth="203.0"/>
</children>
</HBox>
</children>