1. 新增了多窗口切换功能
2. 新增多个example示例可供使用参考 3. 修正信号收发机制的bug 4. 规范化部分代码,并加以部分注释 5. 修改README
This commit is contained in:
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||
</state>
|
||||
</component>
|
||||
2
.idea/compiler.xml
generated
2
.idea/compiler.xml
generated
@@ -15,7 +15,7 @@
|
||||
</component>
|
||||
<component name="JavacSettings">
|
||||
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
|
||||
<module name="JavaFx-Plus" options="-bootclasspath C:/java/jdk/jre\lib\rt.jar;C:/java/jdk/jre\lib\jce.jar -Xlint:deprecation" />
|
||||
<module name="JavaFx-Plus" options="-bootclasspath /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre\lib\rt.jar;/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre\lib\jce.jar -Xlint:deprecation" />
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/dictionaries/suisui.xml
generated
Normal file
8
.idea/dictionaries/suisui.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="suisui">
|
||||
<words>
|
||||
<w>biubiusuisui</w>
|
||||
<w>scau</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
||||
1231
.idea/workspace.xml
generated
1231
.idea/workspace.xml
generated
File diff suppressed because it is too large
Load Diff
514
README.md
514
README.md
@@ -1,44 +1,54 @@
|
||||
# JavaFX-Plus
|
||||
|
||||
- [JavaFX-Plus](#javafx-plus)
|
||||
* [前言](#--)
|
||||
+ [开发进程](#----)
|
||||
* [特色](#--)
|
||||
+ [信号机制](#----)
|
||||
+ [JavaBean 和 JavaFxBean](#javabean---javafxbean)
|
||||
+ [可拖动窗口和可伸缩窗口](#-----------)
|
||||
+ [Spring支持](#spring--)
|
||||
+ [数据表达式绑定](#-------)
|
||||
- [Bean和View绑定](#bean-view--)
|
||||
- [View和View绑定](#view-view--)
|
||||
+ [模块化开发](#-----)
|
||||
- [介绍](#--)
|
||||
- [如何创建模块](#------)
|
||||
- [scenebuilder中导入刚刚生成的上面的控件](#scenebuilder-------------)
|
||||
* [如何使用这个框架](#--------)
|
||||
+ [内置注解](#----)
|
||||
+ [两个工厂和一个context](#-------context)
|
||||
* [创建第一个程序](#-------)
|
||||
* [前言](#前言)
|
||||
+ [开发进程](#开发进程)
|
||||
* [Maven仓库地址](#Maven仓库地址)
|
||||
* [框架功能描述](#框架功能描述)
|
||||
+ [模块化开发](#模块化开发)
|
||||
- [介绍](#介绍)
|
||||
- [如何创建模块](#如何创建模块)
|
||||
- [scenebuilder中导入刚刚生成的上面的控件](#scenebuilder中导入刚刚生成的上面的控件)
|
||||
+ [与Spring的融合](#与Spring的融合)
|
||||
+ [信号机制](#信号机制)
|
||||
+ [JavaBean与JavaFXBean的转换](#JavaBean与JavaFXBean的转换)
|
||||
+ [可拔插功能](#可拔插功能)
|
||||
+ [数据绑定](#数据绑定)
|
||||
- [Bean和View绑定](#Bean和View绑定)
|
||||
- [View和View绑定](#View和View绑定)
|
||||
- [函数表达式绑定](#函数表达式绑定)
|
||||
+ [多窗口切换功能](#多窗口切换功能)
|
||||
* [框架的使用](#框架的使用)
|
||||
+ [内置注解](#内置注解)
|
||||
+ [两个工厂和一个context](#两个工厂和一个context)
|
||||
* [创建第一个程序](#创建第一个程序)
|
||||
|
||||
|
||||
|
||||
## 前言
|
||||
|
||||
这个框架不是UI美化框架,为了简化javaFX项目开发、为了减少项目之间组件耦合而打造的框架。目前框架主要功能如下图所示。
|
||||
这个框架不是UI美化框架,为了简化javaFX项目开发、为了减少项目之间组件耦合而打造的框架。目前框架主要功能如下图所示:
|
||||
|
||||

|
||||

|
||||
### 开发进程
|
||||
2019年11月25日起项目暂停更新,将会下次发布将会升级为2.0版本,到时候将会提供更多数据绑定操作,以及优化性能。
|
||||
|
||||
- [x] 模块化
|
||||
- [x] 与Spring的融合
|
||||
- [x] 信号机制
|
||||
- [x] 数据绑定
|
||||
- [x] spring结合
|
||||
- [x] JavaBean和JavaFXBean的转换
|
||||
- [x] 可拔插功能(窗口拖动等功能)
|
||||
- [x] 数据绑定
|
||||
- [x] Bean和View的绑定
|
||||
- [x] View和View的绑定
|
||||
- [x] 函数表达式绑定
|
||||
- [x] 多窗口切换功能
|
||||
- [ ] 事件注解绑定
|
||||
- [ ] 函数表达式绑定
|
||||
- [ ] 数据校验
|
||||
- [ ] 键盘事件绑定
|
||||
- [ ] 优化性能
|
||||
|
||||
## 仓库地址
|
||||
## Maven仓库地址
|
||||
```xml
|
||||
|
||||
<dependency>
|
||||
@@ -49,51 +59,130 @@
|
||||
|
||||
```
|
||||
|
||||
## 特色
|
||||
## 框架功能描述
|
||||
|
||||
### 模块化开发
|
||||
|
||||
#### 介绍
|
||||
|
||||
在Java开发过程中很多界面是相似或者重复的,如果能够将这些界面打包成为一个自定义控件,并且通过Scenebuilder拖动就能产生一个控件那将会大大提高我们的开发效率。所以我们提出将不同区域划分为不同的子模块,已达到减少耦合和加速并行开发。一般我们经常把界面分为顶部工具栏,左边导航栏,右侧的内容栏,如果全部内容都写在一个Controller那么将会导致十分臃肿,我们希望将不同的区域划分开来分而治之。
|
||||
|
||||
#### 如何创建模块
|
||||
|
||||
只要新建一个类继承自FXBaseController,而FXBaseController是继承于Pane,这就是JavaFX-Plus的设计思想之一切皆为Pane。在类上标上FXController注解,提供FXML文件的地址。如果设置为FXWindow那么将会把这个Controller以单独的Window显示,这里仅仅几句代码就实现了一个简单的窗口程序。
|
||||
|
||||

|
||||
|
||||
图2 Controller配置
|
||||
|
||||

|
||||
|
||||
图3 显示结果
|
||||
|
||||
#### scenebuilder中导入刚刚生成的上面的控件
|
||||
|
||||

|
||||
|
||||
图4 模块化操作
|
||||
|
||||
|
||||
|
||||
### 与Spring的融合
|
||||
|
||||
可以快速支持Spring和这个框架的融合,只需要一行代码,就可将实例的生成控制转交给容器管理。
|
||||
代码如下:
|
||||
|
||||
```java
|
||||
@FXScan(base = {"cn.edu.scau.biubiusuisui.example.springDemo"})
|
||||
public class SpringDemo extends Application {
|
||||
@Override
|
||||
public void start(Stage primaryStage) throws Exception {
|
||||
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //启动spring
|
||||
FXPlusApplication.start(SpringDemo.class, new BeanBuilder() {
|
||||
@Override
|
||||
public Object getBean(Class type) {
|
||||
return context.getBean(type); //接管FXPlus属性的创建
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### 信号机制
|
||||
|
||||
有两个主要标签一个是FXSender,这个标签作用在方法上,标记这个方法为信号发射方法。可以通过设置name修改这个信号发射方法的名称,默认是函数名字。
|
||||
有两个主要标签一个是FXSender,这个标签作用在函数上,标记这个方法为信号发射函数。可以通过设置name修改这个信号发射函数的名称,默认是函数名字。
|
||||
|
||||
发射信号会被订阅这个发射函数的所有FXReceiver接收,并且发射函数的返回值会作为参数传进这个函数之中。而且这种发送和接受关系是全局的,只要是注册了的Controller都可以进行接受,不局限于同一个Controller。
|
||||
发射信号会被订阅了这个发射函数的所有FXReceiver接收,并且发射函数的返回值会作为参数传进这个函数之中。而且这种发送和接收关系是全局的,只要是注册了的Controller都可以进行接收,不局限于同一个Controller。
|
||||
|
||||
我们通过一个简单的代码来理解一下。
|
||||
我们通过一个简单的代码来理解一下,主要实现自定义组件导航栏TopBar,主界面中包含该组件,当用户点击导航栏某些按钮时,能返回主界面相关信息。fxml文件详见resources下的mqDemo文件夹。
|
||||
|
||||
1. 利用JavaFX的模块化,我们设计一个简单的导航栏:
|
||||
|
||||
```java
|
||||
@FXController(path = "Main.fxml")
|
||||
@FXWindow(title = "demo1")
|
||||
public class MainController extends FXBaseController{
|
||||
|
||||
@FXController(path = "mqDemo/topBar.fxml")
|
||||
public class TopBarController extends FXBaseController {
|
||||
@FXML
|
||||
Button btn;
|
||||
|
||||
public void indexClick() {
|
||||
sendToMain("点击[首页]");
|
||||
}
|
||||
@FXML
|
||||
Label label;
|
||||
public void scoreClick() {
|
||||
sendToMain("点击[积分中心]");
|
||||
}
|
||||
@FXML
|
||||
public void questionClick() {
|
||||
sendToMain("点击[问答中心]");
|
||||
}
|
||||
@FXML
|
||||
public void selfClick() {
|
||||
sendToMain("点击[个人中心]");
|
||||
}
|
||||
|
||||
/**
|
||||
鼠标之后,系统通过会发射信号,调用所有订阅这个发射信号函数的方法响应信号
|
||||
*/
|
||||
@FXML //绑定鼠标点击事件
|
||||
@FXSender //标注为信号发射函数
|
||||
public String send(){
|
||||
System.out.println("before sending"); //输出 before sending
|
||||
return "sending msg";
|
||||
* 系统会通过发射信号,调用所有订阅这个发射信号函数的方法,从而响应信号
|
||||
* @param msg
|
||||
* @return
|
||||
*/
|
||||
@FXSender //标注为信号发射函数
|
||||
public String sendToMain(String msg) {
|
||||
return msg;
|
||||
}
|
||||
/**
|
||||
接受者必须指定要订阅的发送者类名+方法名
|
||||
而且发送函数的返回值会注入到接受函数的参数中
|
||||
*/
|
||||
@FXReceiver(name = "MainController:send")
|
||||
public void read(String msg){
|
||||
System.out.println("read " + msg); //输出 read sending msg
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||

|
||||
|
||||
### JavaBean 和 JavaFxBean
|
||||
|
||||
2. 再设计一个主界面,里面包含导航栏
|
||||
|
||||
```java
|
||||
@FXController(path = "mqDemo/main.fxml")
|
||||
@FXWindow(mainStage = true, title = "MQDemo")
|
||||
public class MainController extends FXBaseController {
|
||||
|
||||
@FXML
|
||||
private TextArea outTA;
|
||||
|
||||
/**
|
||||
* 接收者必须指定要订阅的[发送者类名:方法名]
|
||||
* 发送函数的返回值会注入到接收函数的参数中
|
||||
*
|
||||
* @param msg
|
||||
*/
|
||||
@FXReceiver(name = "TopBarController:sendToMain")
|
||||
public void handleTopBar(String msg) {
|
||||
// TODO: 2019/12/8
|
||||
// 处理导航栏的点击事件
|
||||
outTA.appendText(msg + "\n");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||

|
||||
|
||||
### JavaBean与JavaFXBean的转换
|
||||
|
||||
一般我们写的JavaBean都是基本类型的,但是JavaFXBean的设计哲学是这些属性都应该是JavaFX定义的Property类型,这十分不利于我们的开发,我们如何在不修改JavaBean的条件下,使用到JavaFX的Property的一些优良方法呢?答案是我们通过反射获得基本类型对应的Property(目前仅限于boolean,double,integer,long,string,float,List等基本类型,不支持封装对象。)
|
||||
|
||||
@@ -203,8 +292,10 @@ public class Student {
|
||||
|
||||
直接操作JavaBean类,就会通过动态绑定修改界面,不需要讲JavaBean转换为JavaFX Bean可以减少开发中的类型转换。
|
||||
|
||||
### 可拖动窗口和可伸缩窗口
|
||||
在Javafx中如果一个窗口隐藏了标题栏那么这个窗口也就没办法拖动和伸缩了,在JavaFX-Plus中你就不需有这种烦恼,只需要在@FXWindow中设置
|
||||
### 可拔插功能
|
||||
|
||||
在本框架中实现了窗口可拖动和窗口可伸缩,在Javafx中如果一个窗口隐藏了标题栏那么这个窗口也就没办法拖动和伸缩了,在JavaFX-Plus中你就不需有这种烦恼,只需要在@FXWindow中设置
|
||||
|
||||
```java
|
||||
@FXWindow(title = "demo1",dragable = true,style = StageStyle.UNDECORATED)
|
||||
```
|
||||
@@ -215,30 +306,12 @@ public class Student {
|
||||
|
||||

|
||||
|
||||
### Spring支持
|
||||
可以快速支持Spring和这个框架的融合,只需要一行代码,就可将实例的生成控制转交给容器管理。
|
||||
代码如下:
|
||||
```java
|
||||
@FXScan(base = {"cn.edu.scau.biubiusuisui.example.springDemo"})
|
||||
public class SpringDemo extends Application {
|
||||
@Override
|
||||
public void start(Stage primaryStage) throws Exception {
|
||||
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //启动spring
|
||||
FXPlusApplication.start(SpringDemo.class, new BeanBuilder() {
|
||||
@Override
|
||||
public Object getBean(Class type) {
|
||||
return context.getBean(type); //接管FXPlus属性的创建
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
### 数据绑定
|
||||
|
||||
```
|
||||
与之相关的注解有`@FXBind`,注解在JavaFX控件的字段上面,标明该变量的绑定方式和绑定属性,类似于Vue中的界面绑定。目前已实现Bean和View的绑定、View和View的绑定、函数表达式的绑定
|
||||
|
||||
### 数据表达式绑定
|
||||
#### Bean和View绑定
|
||||
在JavaFX控件的字段上面添加@FXbind可以绑定属性,类似于Vue中的界面绑定,但是不同的是,这里的绑定可以是普通Bean和View绑定,可以是View和View绑定,也可以是Bean和Bean绑定(不推荐)。
|
||||
如下面代码,通过FXBind将Studen的姓名与文本框输入内容绑定,学生的密码和密码框输入框内容绑定,完全简化了数据传递操作,代码中完全没有出现界面数据传输到控制器代码。
|
||||
如下面代码,通过FXBind将Student的姓名与文本框输入内容绑定,学生的密码和密码框输入框内容绑定,完全简化了数据传递操作,代码中完全没有出现界面数据传输到控制器代码。
|
||||
例子:
|
||||
|
||||
```java
|
||||
@@ -253,8 +326,9 @@ public class SpringDemo extends Application {
|
||||
|
||||
@FXML
|
||||
private PasswordField psw;
|
||||
|
||||
@FXML
|
||||
private Label label;
|
||||
private Label pswMsg;
|
||||
|
||||
@FXML
|
||||
void login(ActionEvent event) {
|
||||
@@ -272,7 +346,10 @@ public class SpringDemo extends Application {
|
||||
如图所示:
|
||||

|
||||
|
||||
|
||||
|
||||
#### View和View绑定
|
||||
|
||||
```java
|
||||
@FXBind("text=${psw.text}")
|
||||
@FXML
|
||||
@@ -281,62 +358,273 @@ private Label pswMsg;//任何psw中的内容都会同步到pswMsg中
|
||||
如图所示
|
||||

|
||||
|
||||
### 模块化开发
|
||||
|
||||
|
||||
#### 函数表达式绑定
|
||||
|
||||
示例代码可见`cn.edu.scau.biubiusuisui.example.listDemo`和 `cn.edu.scau.biubiusuisui.actionDemo`,以下举actionDemo为例。
|
||||
|
||||
1. 使用方法
|
||||
|
||||
使用在界面Controller类中的JavaFX控件上,与以上两种绑定类似,以`${}`为外部标识,当该绑定属于函数表达式绑定时,需要在函数名前加`@`。
|
||||
|
||||
```java
|
||||
@FXBind("text=${@toUs(time.text)}") // 将Label中的text和toUs()函数的返回值绑定
|
||||
private Label us;
|
||||
```
|
||||
|
||||
2. 示例代码
|
||||
|
||||
如以下代码,实现简单的汇率转换器。
|
||||
|
||||
```java
|
||||
@FXController(path = "actionDemo/actionDemo.fxml")
|
||||
@FXWindow(title = "actionDemo", mainStage = true)
|
||||
public class MainController extends FXBaseController implements Initializable {
|
||||
@FXML
|
||||
@FXBind("text=${@toUs(time.text)}") // 将Label中的text和toUs()函数的返回值绑定
|
||||
private Label us;
|
||||
|
||||
@FXML
|
||||
@FXBind("text=${@toJp(time.text)}")
|
||||
private Label jp;
|
||||
|
||||
@FXML
|
||||
@FXBind("text=${@toUk(time.text)}")
|
||||
private Label uk;
|
||||
|
||||
@FXML
|
||||
private TextField time;
|
||||
|
||||
public String toUs(String value) {
|
||||
double money = Double.valueOf(value);
|
||||
double percent = 0.1454;
|
||||
return String.valueOf(money * percent);
|
||||
}
|
||||
|
||||
public String toJp(String value) {
|
||||
double money = Double.valueOf(value);
|
||||
double percent = 15.797;
|
||||
return String.valueOf(money * percent);
|
||||
}
|
||||
|
||||
public String toUk(String value) {
|
||||
double money = Double.valueOf(value);
|
||||
double percent = 0.1174;
|
||||
return String.valueOf(money * percent);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. 动态演示
|
||||
|
||||
如图所示:
|
||||
|
||||

|
||||
|
||||
### 多窗口切换功能
|
||||
|
||||
#### 介绍
|
||||
|
||||
在Java开发过程中很多界面是相似或者重复的,如果能够将这些界面打包成为一个自定义控件,并且通过Scenebuilder拖动就能产生一个控件那将会大大提高我们的开发效率。所以我们提出将不同区域划分为不同的子模块,已达到减少耦合和加速并行开发。一般我们经常把界面分为顶部工具栏,左边导航栏,右侧的内容栏,如果全部内容都写在一个Controller那么将会导致十分臃肿,我们希望将不同的区域划分开来分而治之。
|
||||
在JavaFX中常常需要多个窗口之间进行切换,比如登录窗口,点击登录后跳转至登录成功/失败窗口,网上部分有关多窗口切换的JavaFX教程实现过程为:在Controller中是实现FXML绑定,并通过外部调用某个show方法来切换窗口。由于本框架已经将FXML绑定这一功能封装,故通过在Controller内部直接初始化Stage并设置参数这一方法并不现实。因此,在本框架中,编写StageController类对Controller进行管理。
|
||||
|
||||
#### 如何创建模块
|
||||
#### 涉及到的注解
|
||||
|
||||
只要新建一个类继承自FXBaseController,而FXBaseController是继承于Pane,这就是JavaFX-Plus的设计思想之一切皆为Pane。在类上标上FXController注解,提供FXML文件的地址。如果设置为FXWindow那么将会把这个Controller以单独的Window显示,这里仅仅几句代码就实现了一个简单的窗口程序。
|
||||
`@FXController`:标记于类上,用于绑定FXML文件,需要注意的是标记了`FXController`只能标记这是一个控件。
|
||||
|
||||

|
||||
`@FXWindow`:标记于类上,标记这个Controller需要以窗口显示,只有需要以单独窗口显示时才会被重定向。
|
||||
|
||||
图2 Controller配置
|
||||
`@FXRedirect`:标记于函数上,标记该函数用于处理重定向。
|
||||
|
||||

|
||||
#### 规定
|
||||
|
||||
图3 显示结果
|
||||
本框架规定,当需要使用`@FXRedirect`标记函数处理重定向时,函数必须是返回String类型的函数,且返回已注册的Controller名,如需要重定向至登录成功界面,控制器为`SuccessController`,则需要写上`return "SuccessController"。
|
||||
|
||||
#### scenebuilder中导入刚刚生成的上面的控件
|
||||
#### 使用方法
|
||||
|
||||

|
||||
1. `FXRedirect`注解的使用如下:
|
||||
|
||||
图4 模块化操作
|
||||
```java
|
||||
@FXRedirect
|
||||
public String redirectToRegister() {
|
||||
return "RegisterController";
|
||||
}
|
||||
|
||||
@FXML
|
||||
@FXRedirect(close = false) //测试弹窗
|
||||
public String redirectToDialog() {
|
||||
return "DialogController";
|
||||
}
|
||||
```
|
||||
|
||||
## 如何使用这个框架
|
||||
close是标明是否需要关闭当前的窗口,默认为true,即默认当跳转另一个窗口时关闭当前窗口。
|
||||
|
||||
2. 创建程序初始界面Controller,此处举例为登录界面
|
||||
|
||||
```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("点击注册.....");
|
||||
redirectToRegister();
|
||||
}
|
||||
|
||||
@FXRedirect
|
||||
public String redirectToRegister() {
|
||||
return "RegisterController";
|
||||
}
|
||||
|
||||
@FXML
|
||||
@FXRedirect(close = false) //测试弹窗
|
||||
public String redirectToDialog() {
|
||||
return "DialogController";
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
3. 编写需要跳转的界面Controller,比如登录时,尚无账号跳转至注册界面和测试弹窗的Controller
|
||||
|
||||
```java
|
||||
@FXController(path = "redirectDemo/register.fxml")
|
||||
@FXWindow(title = "register")
|
||||
public class RegisterController extends FXBaseController {
|
||||
@FXML
|
||||
private TextField usernameTF;
|
||||
@FXML
|
||||
private TextField emailTF;
|
||||
@FXML
|
||||
private PasswordField passwordPF;
|
||||
|
||||
@FXML
|
||||
private PasswordField confirmPasswordPF;
|
||||
|
||||
@FXML
|
||||
public void registerClick() {
|
||||
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void loginClick() {
|
||||
redirectToLogin();
|
||||
}
|
||||
|
||||
@FXRedirect
|
||||
public String redirectToLogin() {
|
||||
return "LoginController";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
@FXController(path = "redirectDemo/dialog.fxml")
|
||||
@FXWindow(title = "弹窗")
|
||||
public class DialogController extends FXBaseController {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 示例演示
|
||||
|
||||
本次示例源码已存于`cn.edu.scau.biubiusuisui.example.redirectDemo`,fxml文件于resources下的redirectDemo文件夹中。
|
||||
|
||||
1. 跳转至另一个窗口(关闭原窗口)
|
||||
|
||||

|
||||
|
||||
2. 弹窗形式弹出窗口(不关闭原窗口)
|
||||
|
||||

|
||||
|
||||
#### 不足之处
|
||||
|
||||
暂未实现携带数据的窗口跳转,目前只实现纯粹跳转到另一个Controller。
|
||||
|
||||
|
||||
|
||||
## 框架的使用
|
||||
### 内置注解
|
||||
|
||||
| 名字 | 作用 | 参数 | 要求 |
|
||||
| ------------- | ------------------------------------------------------------ | --------------------------------------- | -------------------- |
|
||||
| @FXData | 表面这个普通bean要装配成javafxBean | fx_id | 重新命名 |
|
||||
| @FXScan | 扫描@FXEntity和@FXController注解标记的类 | 要扫描的目录 | 默认当前目录之下所有 |
|
||||
| @FXController | 标记这个类为控件 | fxml文件地址 | 无 |
|
||||
| @FXWindow | 标记这个控件要以单独窗口显示 | title是窗口名字,也可以设置窗口长度宽度 | 无 |
|
||||
| @FXEntity | 标记JavaBean系统会自动识别@FXField然后包装JavaBean为JavaFXBean | 重命名 | |
|
||||
| @FXField | 代表这个属性要映射为Property属性 | | |
|
||||
| @FXSender | 信号发送者 | name可以重命名信号 | |
|
||||
| @FXReceiver | 信号接收函数 | name是订阅的发射者函数名 | 不可空 |
|
||||
|
||||
|
||||
| 名字 | 作用 | 参数 | 要求 |
|
||||
| ------------- | ------------------------------------------------------------ | --------------------------------------- | ---------------------------------------- |
|
||||
| @FXData | 标明这个普通bean要装配成javafxBean | fx_id | 重新命名 |
|
||||
| @FXScan | 扫描@FXEntity和@FXController注解标记的类 | 要扫描的目录 | 默认当前目录之下所有 |
|
||||
| @FXController | 标记这个类为控件 | path:fxml文件地址 | 无 |
|
||||
| @FXWindow | 标记这个控件要以单独窗口显示 | title是窗口名字,也可以设置窗口长度宽度 | 无 |
|
||||
| @FXEntity | 标记JavaBean系统会自动识别@FXField然后包装JavaBean为JavaFXBean | 重命名 | |
|
||||
| @FXField | 代表这个属性要映射为Property属性 | | |
|
||||
| @FXSender | 信号发送者 | name:重命名信号 | |
|
||||
| @FXReceiver | 信号接收函数 | name:订阅的发射者函数名 | 不可空 |
|
||||
| @FXRedirect | 标记函数为重定向函数 | close:是否关闭当前窗口 | 返回值为某个使用了FXView注解的Controller |
|
||||
|
||||
### 两个工厂和一个context
|
||||
|
||||
1. 两个工厂
|
||||
|
||||
在JavaFX-Plus中所有Controller对象和FXEnity对象都必须通过工厂创建。
|
||||
|
||||
```
|
||||
```java
|
||||
student = (Student) FXEntityFactory.getInstance().createJavaBeanProxy(Student.class); //工厂产生一个学生
|
||||
```
|
||||
|
||||
通过工厂创建JavaBean,在创建同时工厂会对JavaBean代理并且包装对应的Property属性。
|
||||
通过工厂创建JavaBean,在创建的同时,工厂会对JavaBean代理并且包装对应的Property属性。
|
||||
|
||||
```
|
||||
```java
|
||||
MainController mainController = (MainController)FXFactory.getFXController(MainController.class);
|
||||
```
|
||||
|
||||
2. 一个context
|
||||
|
||||
存储所有用@FXController注解后的Controller和FXEntity的代理类。
|
||||
|
||||
```java
|
||||
public class FXPlusContext {
|
||||
|
||||
private FXPlusContext(){}
|
||||
|
||||
private static Map<String, List<FXBaseController>> controllerContext = new ConcurrentHashMap<>(); //FXController控制器注册表
|
||||
|
||||
private static Map<Object, FXEntityProxy> beanMap = new ConcurrentHashMap<>(); // Object注册为FXEntityObject
|
||||
|
||||
|
||||
public static void addController(FXBaseController fxBaseController){
|
||||
List<FXBaseController> controllers = controllerContext.get(fxBaseController.getName());
|
||||
if(controllers == null){
|
||||
controllers = new LinkedList<>();
|
||||
}
|
||||
controllers.add(fxBaseController);
|
||||
}
|
||||
|
||||
public static List<FXBaseController> getControllers(String key){
|
||||
return controllerContext.get(key);
|
||||
}
|
||||
|
||||
public static FXEntityProxy getProxyByBeanObject(Object object){
|
||||
return beanMap.get(object);
|
||||
}
|
||||
|
||||
public static void setProxyByBeanObject(Object object,FXEntityProxy fxEntityProxy){
|
||||
beanMap.put(object,fxEntityProxy);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 创建第一个程序
|
||||
|
||||
1. 主程序类。
|
||||
|
||||
```java
|
||||
@FXScan(base = {"cn.edu.scau.biubiusuisui.example"}) //会扫描带FXController和FXEntity的类进行初始化
|
||||
public class Demo extends Application {
|
||||
@@ -347,24 +635,20 @@ public class Demo extends Application {
|
||||
}
|
||||
|
||||
```
|
||||
接下来我们生成FXML和Controller
|
||||
2. 接下来我们生成FXML和Controller
|
||||
|
||||
```java
|
||||
@FXController(path = "Main.fxml")
|
||||
@FXWindow(title = "demo1")
|
||||
public class MainController extends FXBaseController{
|
||||
|
||||
@FXML
|
||||
private ResourceBundle resources;
|
||||
|
||||
@FXML
|
||||
private URL location;
|
||||
|
||||
@FXML
|
||||
private Button addBtn;
|
||||
|
||||
@FXML
|
||||
private Button delBtn;
|
||||
|
||||
@FXML
|
||||
private ListView<String> list;
|
||||
|
||||
@@ -382,9 +666,9 @@ public class MainController extends FXBaseController{
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
student = (Student) FXEntityFactory.createJavaBeanProxy(Student.class);
|
||||
Property property = FXPlusContext.getEntityPropertyByName(student, "list");
|
||||
list.itemsProperty().bind(property);
|
||||
student = (Student) FXEntityFactory.createJavaBeanProxy(Student.class); // 从工厂中拿到将JavaBean转换得到的JavaFXBean
|
||||
Property listProperty = FXPlusContext.getEntityPropertyByName(student, "list");
|
||||
list.itemsProperty().bind(listProperty);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,7 +680,7 @@ Studen类的定义如下
|
||||
@FXEntity
|
||||
public class Student {
|
||||
|
||||
@FXField
|
||||
@FXField //标记该属性是否被生成对应的Property
|
||||
private String name;
|
||||
|
||||
@FXField
|
||||
@@ -411,6 +695,8 @@ public class Student {
|
||||
}
|
||||
```
|
||||
|
||||
请注意,FXML文件的根标签必须为`<fx:root>`。
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
|
||||
BIN
doc/JavaFX-Plus.png
Normal file
BIN
doc/JavaFX-Plus.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 451 KiB |
BIN
doc/actionDemo/20191210-175409-actionDemo.gif
Normal file
BIN
doc/actionDemo/20191210-175409-actionDemo.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 MiB |
@@ -0,0 +1,17 @@
|
||||
package cn.edu.scau.biubiusuisui.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @author suiyu_yang
|
||||
* @description 重定向的注解
|
||||
* @date 2019/12/3 12:53
|
||||
* @email suiyu_yang@163.com
|
||||
*/
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
@Inherited
|
||||
public @interface FXRedirect {
|
||||
boolean close() default true;
|
||||
}
|
||||
@@ -8,17 +8,16 @@ import cn.edu.scau.biubiusuisui.factory.FXControllerFactory;
|
||||
import cn.edu.scau.biubiusuisui.function.FXWindowParser;
|
||||
import cn.edu.scau.biubiusuisui.utils.ClassUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @Author jack
|
||||
* @Date:2019/6/25 2:54
|
||||
*/
|
||||
public class FXPlusApplication {
|
||||
public class FXPlusApplication {
|
||||
|
||||
private static FXWindowParser windowAnnotationParser = new FXWindowParser();
|
||||
|
||||
@@ -26,26 +25,26 @@ public class FXPlusApplication {
|
||||
|
||||
private static BeanBuilder beanBuilder;
|
||||
|
||||
public static boolean IS_SCENE_BUILDER = true;
|
||||
public static boolean IS_SCENE_BUILDER = true;
|
||||
|
||||
public static void start(Class clazz, BeanBuilder beanBuilder){
|
||||
public static void start(Class clazz, BeanBuilder beanBuilder) {
|
||||
IS_SCENE_BUILDER = false;
|
||||
FXPlusApplication.beanBuilder = beanBuilder;
|
||||
Annotation []annotations = clazz.getDeclaredAnnotations();
|
||||
for(Annotation annotation : annotations){
|
||||
if(FXScan.class.equals(annotation.annotationType())){
|
||||
String []dirs = ((FXScan)annotation).base();
|
||||
Annotation[] annotations = clazz.getDeclaredAnnotations();
|
||||
for (Annotation annotation : annotations) {
|
||||
if (FXScan.class.equals(annotation.annotationType())) {
|
||||
String[] dirs = ((FXScan) annotation).base();
|
||||
Set<String> sets = new HashSet<>();
|
||||
for(String dir : dirs){
|
||||
for (String dir : dirs) {
|
||||
sets.add(dir);
|
||||
}
|
||||
Set<String> classNames = new HashSet<>();
|
||||
for(String dir:sets){
|
||||
for (String dir : sets) {
|
||||
ClassUtils classUtils = new ClassUtils();
|
||||
List<String> temps = classUtils.scanAllClassName(dir);
|
||||
for(String className:temps){
|
||||
for (String className : temps) {
|
||||
try {
|
||||
loadFXPlusClass(className,beanBuilder);
|
||||
loadFXPlusClass(className, beanBuilder);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -54,14 +53,15 @@ public class FXPlusApplication {
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void start(Class clazz){
|
||||
start(clazz,DEFALUT_BEAN_FACTORY);
|
||||
|
||||
public static void start(Class clazz) {
|
||||
start(clazz, DEFALUT_BEAN_FACTORY);
|
||||
}
|
||||
|
||||
private static void loadFXPlusClass(String className,BeanBuilder beanBuilder) throws ClassNotFoundException {
|
||||
private static void loadFXPlusClass(String className, BeanBuilder beanBuilder) throws ClassNotFoundException {
|
||||
Class clazz = Class.forName(className);
|
||||
if(clazz.getAnnotation(FXWindow.class)!=null) {
|
||||
FXControllerFactory.loadMainStage(clazz, beanBuilder);
|
||||
if (clazz.getAnnotation(FXWindow.class) != null) {
|
||||
FXControllerFactory.loadStage(clazz, beanBuilder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package cn.edu.scau.biubiusuisui.entity;
|
||||
|
||||
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.utils.StringUtils;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
@@ -17,31 +17,25 @@ import java.lang.annotation.Annotation;
|
||||
*/
|
||||
|
||||
/**
|
||||
* In JavaFX-Plus Framework Controller
|
||||
* We use MVC model
|
||||
* V means view which stand for fxml
|
||||
* C means controller which stand for FXBaseController instance
|
||||
* M means model which is base cn.edu.scau.biubiusuisui.entity in your program
|
||||
* Every BaseController has a name which is used for identifying different <strong>instance</strong>
|
||||
*
|
||||
* In JavaFX-Plus Framework Controller
|
||||
* We use MVC model
|
||||
* V means view which stand for fxml
|
||||
* C means controller which stand for FXBaseController instance
|
||||
* M means model which is base cn.edu.scau.biubiusuisui.entity in your program
|
||||
* Every BaseController has a name which is used for identifying different <strong>instance</strong>
|
||||
*/
|
||||
public class FXBaseController extends Pane {
|
||||
public class FXBaseController extends Pane {
|
||||
|
||||
protected String name = "";
|
||||
|
||||
|
||||
private Stage stage;
|
||||
|
||||
|
||||
private boolean isController = false;
|
||||
private boolean isWindow = false;
|
||||
|
||||
private boolean isWindows = false;
|
||||
|
||||
public FXBaseController(String name){
|
||||
public FXBaseController(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public FXBaseController(){
|
||||
public FXBaseController() {
|
||||
FXController fxController = null;
|
||||
Annotation[] annotations = getClass().getAnnotations();
|
||||
// Find FXController cn.edu.scau.biubiusuisui.annotation
|
||||
@@ -50,36 +44,52 @@ public class FXBaseController extends Pane {
|
||||
fxController = (FXController) annotation;
|
||||
isController = true;
|
||||
}
|
||||
// 添加赋予是否为窗口的逻辑
|
||||
if (annotation.annotationType().equals(FXWindow.class)) {
|
||||
isWindow = true;
|
||||
}
|
||||
}
|
||||
//load fxml file to show panel in scene builder
|
||||
if(isController && FXPlusApplication.IS_SCENE_BUILDER == true) {
|
||||
if (isController && FXPlusApplication.IS_SCENE_BUILDER == true) {
|
||||
FXMLLoaderPlus fxmlLoader = new FXMLLoaderPlus(getClass().getClassLoader().getResource(fxController.path()));
|
||||
fxmlLoader.setRoot(this);
|
||||
fxmlLoader.setController(this);
|
||||
fxmlLoader.setShow(true);
|
||||
System.out.println("?");
|
||||
// System.out.println("?");
|
||||
try {
|
||||
fxmlLoader.load();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void initialize() {
|
||||
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
if("".equals(name)){
|
||||
return StringUtils.getBaseClassName(getClass().getSimpleName());
|
||||
}else{
|
||||
return StringUtils.getBaseClassName(getClass().getSimpleName()) +"#"+name;
|
||||
/**
|
||||
* 唤起舞台
|
||||
*/
|
||||
public void showStage() {
|
||||
if (isWindow) {
|
||||
this.stage.show();
|
||||
}
|
||||
}
|
||||
|
||||
public void closeStage() {
|
||||
if (isWindow) {
|
||||
this.stage.close();
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
if ("".equals(name) || name == null) { // 原本无“name == null”判断条件,会出错
|
||||
return StringUtils.getBaseClassName(getClass().getSimpleName());
|
||||
} else {
|
||||
return StringUtils.getBaseClassName(getClass().getSimpleName()) + "#" + name;
|
||||
}
|
||||
}
|
||||
public void doInit(){}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
@@ -93,12 +103,12 @@ public class FXBaseController extends Pane {
|
||||
isController = controller;
|
||||
}
|
||||
|
||||
public boolean isWindows() {
|
||||
return isWindows;
|
||||
public boolean isWindow() {
|
||||
return isWindow;
|
||||
}
|
||||
|
||||
public void setWindows(boolean windows) {
|
||||
isWindows = windows;
|
||||
public void setWindow(boolean window) {
|
||||
isWindow = window;
|
||||
}
|
||||
|
||||
public Stage getStage() {
|
||||
|
||||
@@ -4,10 +4,11 @@ import cn.edu.scau.biubiusuisui.annotation.FXField;
|
||||
import javafx.beans.property.Property;
|
||||
|
||||
/**
|
||||
* 将Controller中的JavaFX的field包装成FXFieldWrapper
|
||||
* @Author jack
|
||||
* @Date:2019/6/28 10:03
|
||||
*/
|
||||
public class FXFieldWarpper {
|
||||
public class FXFieldWrapper {
|
||||
|
||||
private FXField fxField;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package cn.edu.scau.biubiusuisui.entity;
|
||||
|
||||
import cn.edu.scau.biubiusuisui.proxy.FXEntityProxy;
|
||||
import javafx.beans.property.Property;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -44,5 +43,4 @@ public class FXPlusContext {
|
||||
public static void setProxyByBeanObject(Object object,FXEntityProxy fxEntityProxy){
|
||||
beanMap.put(object,fxEntityProxy);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package cn.edu.scau.biubiusuisui.example.actionDemo;
|
||||
|
||||
import cn.edu.scau.biubiusuisui.annotation.FXScan;
|
||||
import cn.edu.scau.biubiusuisui.annotation.FXSender;
|
||||
import cn.edu.scau.biubiusuisui.config.FXPlusApplication;
|
||||
import javafx.application.Application;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
@@ -2,27 +2,25 @@ package cn.edu.scau.biubiusuisui.example.actionDemo;
|
||||
|
||||
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.scene.control.Button;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.PasswordField;
|
||||
import javafx.scene.control.TextField;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.net.URL;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* @Author jack
|
||||
* @Date:2019/7/27 1:43
|
||||
*/
|
||||
@FXController(path = "actionDemo.fxml")
|
||||
@FXWindow(title = "actionDemo")
|
||||
public class MainController extends FXBaseController {
|
||||
|
||||
|
||||
|
||||
@FXController(path = "actionDemo/actionDemo.fxml")
|
||||
@FXWindow(title = "actionDemo", mainStage = true)
|
||||
public class MainController extends FXBaseController implements Initializable {
|
||||
@FXML
|
||||
@FXBind("text=${@toUs(time.text)}")
|
||||
private Label us;
|
||||
@@ -31,28 +29,43 @@ public class MainController extends FXBaseController {
|
||||
@FXBind("text=${@toJp(time.text)}")
|
||||
private Label jp;
|
||||
|
||||
@FXML
|
||||
private TextField time;
|
||||
|
||||
@FXML
|
||||
@FXBind("text=${@toUk(time.text)}")
|
||||
private Label uk;
|
||||
|
||||
public String toUs(String value){
|
||||
@FXML
|
||||
private TextField time;
|
||||
|
||||
public String toUs(String value) {
|
||||
double money = Double.valueOf(value);
|
||||
double percent = 0.1454;
|
||||
return String.valueOf(money * percent);
|
||||
}
|
||||
|
||||
public String toJp(String value){
|
||||
public String toJp(String value) {
|
||||
double money = Double.valueOf(value);
|
||||
double percent = 15.797;
|
||||
return String.valueOf(money * percent);
|
||||
}
|
||||
|
||||
public String toUk(String value){
|
||||
public String toUk(String value) {
|
||||
double money = Double.valueOf(value);
|
||||
double percent = 0.1174;
|
||||
return String.valueOf(money * percent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
time.setText("0");
|
||||
time.textProperty().addListener(new ChangeListener<String>() {
|
||||
@Override
|
||||
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
|
||||
if (null == newValue || "".equals(newValue)) {
|
||||
time.setText("0");
|
||||
} else if (!newValue.matches("^[0-9]*$")) {
|
||||
time.setText(oldValue);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,13 +5,10 @@ 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.ObservableValue;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.ListView;
|
||||
import javafx.scene.control.TextField;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -19,29 +16,29 @@ import java.util.ArrayList;
|
||||
* @Author jack
|
||||
* @Date:2019/7/27 1:43
|
||||
*/
|
||||
@FXController(path = "listDemo.fxml")
|
||||
@FXWindow(title = "actionDemo",mainStage = true)
|
||||
@FXController(path = "listDemo/listDemo.fxml")
|
||||
@FXWindow(title = "listDemo", mainStage = true)
|
||||
public class MainController extends FXBaseController {
|
||||
|
||||
private static int count = 0;
|
||||
|
||||
@FXData
|
||||
User user = new User();
|
||||
|
||||
|
||||
@FXML
|
||||
@FXBind("items=${@toList(user.names)}")
|
||||
private ListView<String> list;
|
||||
private ListView<String> userNameListView;
|
||||
|
||||
|
||||
public ObservableList hello(){
|
||||
return FXCollections.observableList(new ArrayList<String>(){{add("hello");}});
|
||||
}
|
||||
|
||||
public ObservableList toList(ArrayList list){
|
||||
return FXCollections.observableList(list);
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void addName(){
|
||||
user.addNames("hello");
|
||||
public void addUserName() {
|
||||
user.addNames("Jack\t" + (count++));
|
||||
}
|
||||
|
||||
public ObservableList toList(ArrayList list) {
|
||||
if (list == null) {
|
||||
return null;
|
||||
}
|
||||
return FXCollections.observableList(list);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,20 +17,20 @@ public class User {
|
||||
@FXField
|
||||
private String password;
|
||||
|
||||
public User() {
|
||||
names.add("hello ");
|
||||
names.add("test");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void addNames(String name){
|
||||
names.add(name);
|
||||
}
|
||||
@FXField
|
||||
private ArrayList<String> names = new ArrayList<>();
|
||||
|
||||
|
||||
public User() {
|
||||
// names.add("hello ");
|
||||
// names.add("test");
|
||||
}
|
||||
|
||||
|
||||
public void addNames(String name) {
|
||||
names.add(name);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.edu.scau.biubiusuisui.example.mqDemo;
|
||||
|
||||
import cn.edu.scau.biubiusuisui.annotation.FXScan;
|
||||
import cn.edu.scau.biubiusuisui.config.FXPlusApplication;
|
||||
import javafx.application.Application;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
/**
|
||||
* @author suiyu_yang
|
||||
* @description
|
||||
* @date 2019/12/8 13:17
|
||||
* @email suiyu_yang@163.com
|
||||
*/
|
||||
@FXScan(base = "cn.edu.scau.biubiusuisui.example.mqDemo")
|
||||
public class MQDemo extends Application {
|
||||
@Override
|
||||
public void start(Stage primaryStage) throws Exception {
|
||||
FXPlusApplication.start(MQDemo.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package cn.edu.scau.biubiusuisui.example.mqDemo;
|
||||
|
||||
import cn.edu.scau.biubiusuisui.annotation.FXController;
|
||||
import cn.edu.scau.biubiusuisui.annotation.FXReceiver;
|
||||
import cn.edu.scau.biubiusuisui.annotation.FXWindow;
|
||||
import cn.edu.scau.biubiusuisui.entity.FXBaseController;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.TextArea;
|
||||
|
||||
/**
|
||||
* @author suiyu_yang
|
||||
* @description 主界面
|
||||
* @date 2019/12/8 13:17
|
||||
* @email suiyu_yang@163.com
|
||||
*/
|
||||
@FXController(path = "mqDemo/main.fxml")
|
||||
@FXWindow(mainStage = true, title = "MQDemo")
|
||||
public class MainController extends FXBaseController {
|
||||
|
||||
@FXML
|
||||
private TextArea outTA;
|
||||
|
||||
/**
|
||||
* 接收者必须指定要订阅的[发送者类名:方法名]
|
||||
* 发送函数的返回值会注入到接收函数的参数中
|
||||
*
|
||||
* @param msg
|
||||
*/
|
||||
@FXReceiver(name = "TopBarController:sendToMain")
|
||||
public void handleTopBar(String msg) {
|
||||
// TODO: 2019/12/8
|
||||
// 处理导航栏的点击事件
|
||||
outTA.appendText(msg + "\n");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package cn.edu.scau.biubiusuisui.example.mqDemo;
|
||||
|
||||
import cn.edu.scau.biubiusuisui.annotation.FXController;
|
||||
import cn.edu.scau.biubiusuisui.annotation.FXSender;
|
||||
import cn.edu.scau.biubiusuisui.entity.FXBaseController;
|
||||
import javafx.fxml.FXML;
|
||||
|
||||
/**
|
||||
* @author suiyu_yang
|
||||
* @description 导航栏示例
|
||||
* @date 2019/12/8 13:17
|
||||
* @email suiyu_yang@163.com
|
||||
*/
|
||||
@FXController(path = "mqDemo/topBar.fxml")
|
||||
public class TopBarController extends FXBaseController {
|
||||
|
||||
@FXML
|
||||
public void indexClick() {
|
||||
sendToMain("点击[首页]");
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void scoreClick() {
|
||||
sendToMain("点击[积分中心]");
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void questionClick() {
|
||||
sendToMain("点击[问答中心]");
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void selfClick() {
|
||||
sendToMain("点击[个人中心]");
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统会通过发射信号,调用所有订阅这个发射信号函数的方法,从而响应信号
|
||||
*
|
||||
* @param msg
|
||||
* @return
|
||||
*/
|
||||
@FXSender //标注为信号发射函数
|
||||
public String sendToMain(String msg) {
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package cn.edu.scau.biubiusuisui.example.redirectDemo;
|
||||
|
||||
import cn.edu.scau.biubiusuisui.annotation.FXController;
|
||||
import cn.edu.scau.biubiusuisui.annotation.FXWindow;
|
||||
import cn.edu.scau.biubiusuisui.entity.FXBaseController;
|
||||
|
||||
/**
|
||||
* @author suiyu_yang
|
||||
* @description
|
||||
* @date 2019/12/4 21:00
|
||||
* @email suiyu_yang@163.com
|
||||
*/
|
||||
@FXController(path = "redirectDemo/dialog.fxml")
|
||||
@FXWindow(title = "弹窗")
|
||||
public class DialogController extends FXBaseController {
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package cn.edu.scau.biubiusuisui.example.redirectDemo;
|
||||
|
||||
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 javafx.fxml.FXML;
|
||||
import javafx.scene.control.PasswordField;
|
||||
import javafx.scene.control.TextField;
|
||||
|
||||
/**
|
||||
* @author suiyu_yang
|
||||
* @description
|
||||
* @date 2019/12/3 11:53
|
||||
* @email suiyu_yang@163.com
|
||||
*/
|
||||
@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("点击注册.....");
|
||||
redirectToRegister();
|
||||
}
|
||||
|
||||
@FXRedirect
|
||||
public String redirectToRegister() {
|
||||
return "RegisterController";
|
||||
}
|
||||
|
||||
@FXML
|
||||
@FXRedirect(close = false) //弹窗
|
||||
public String redirectToDialog() {
|
||||
return "DialogController";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.edu.scau.biubiusuisui.example.redirectDemo;
|
||||
|
||||
import cn.edu.scau.biubiusuisui.annotation.FXScan;
|
||||
import cn.edu.scau.biubiusuisui.config.FXPlusApplication;
|
||||
import javafx.application.Application;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
/**
|
||||
* @author suiyu_yang
|
||||
* @description 测试重定向功能的Application
|
||||
* @date 2019/12/3 11:52
|
||||
* @email suiyu_yang@163.com
|
||||
*/
|
||||
@FXScan(base = "cn.edu.scau.biubiusuisui.example.redirectDemo")
|
||||
public class RedirectDemo extends Application {
|
||||
@Override
|
||||
public void start(Stage primaryStage) throws Exception {
|
||||
FXPlusApplication.start(RedirectDemo.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package cn.edu.scau.biubiusuisui.example.redirectDemo;
|
||||
|
||||
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 javafx.fxml.FXML;
|
||||
import javafx.scene.control.PasswordField;
|
||||
import javafx.scene.control.TextField;
|
||||
|
||||
/**
|
||||
* @author suiyu_yang
|
||||
* @description
|
||||
* @date 2019/12/4 00:07
|
||||
* @email suiyu_yang@163.com
|
||||
*/
|
||||
@FXController(path = "redirectDemo/register.fxml")
|
||||
@FXWindow(title = "register")
|
||||
public class RegisterController extends FXBaseController {
|
||||
@FXML
|
||||
private TextField usernameTF;
|
||||
|
||||
@FXML
|
||||
private TextField emailTF;
|
||||
@FXML
|
||||
private PasswordField passwordPF;
|
||||
|
||||
@FXML
|
||||
private PasswordField confirmPasswordPF;
|
||||
|
||||
@FXML
|
||||
public void registerClick() {
|
||||
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void loginClick() {
|
||||
redirectToLogin();
|
||||
}
|
||||
|
||||
@FXRedirect
|
||||
public String redirectToLogin() {
|
||||
return "LoginController";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package cn.edu.scau.biubiusuisui.example.redirectDemo;
|
||||
|
||||
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 javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.Label;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* @author suiyu_yang
|
||||
* @description 登录成功的Controller
|
||||
* @date 2019/12/3 12:43
|
||||
* @email suiyu_yang@163.com
|
||||
*/
|
||||
@FXController(path = "redirectDemo/success.fxml")
|
||||
@FXWindow(title = "success")
|
||||
public class SuccessController extends FXBaseController implements Initializable {
|
||||
|
||||
@FXML
|
||||
private Label usernameLabel;
|
||||
|
||||
@FXML
|
||||
private Label passwordLabel;
|
||||
|
||||
|
||||
@FXML
|
||||
@FXRedirect
|
||||
public String redirectToLogin() {
|
||||
return "LoginController";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,13 +12,13 @@ import cn.edu.scau.biubiusuisui.expression.data.ExpressionParser;
|
||||
import cn.edu.scau.biubiusuisui.function.FXWindowParser;
|
||||
import cn.edu.scau.biubiusuisui.messageQueue.MessageQueue;
|
||||
import cn.edu.scau.biubiusuisui.proxy.FXControllerProxy;
|
||||
import cn.edu.scau.biubiusuisui.stage.StageManager;
|
||||
import javafx.collections.ObservableMap;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.URL;
|
||||
|
||||
@@ -92,13 +92,14 @@ public class FXControllerFactory {
|
||||
FXBaseController fxBaseController = null;
|
||||
FXBaseController fxControllerProxy = null;
|
||||
if (fxController != null) {
|
||||
String name = fxController.path();
|
||||
fxmlPath = clazz.getClassLoader().getResource(name);
|
||||
String fxmlPathName = fxController.path();
|
||||
fxmlPath = clazz.getClassLoader().getResource(fxmlPathName);
|
||||
FXMLLoaderPlus fxmlLoader = new FXMLLoaderPlus(fxmlPath);
|
||||
// create a cn.edu.scau.biubiusuisui.proxy for monitoring methods
|
||||
|
||||
fxBaseController = (FXBaseController) beanBuilder.getBean(clazz); //获取controller实例
|
||||
parseData(fxBaseController);
|
||||
|
||||
if (fxBaseController != null) {
|
||||
FXControllerProxy controllerProxy = new FXControllerProxy();
|
||||
fxControllerProxy = (FXBaseController) controllerProxy.getInstance(fxBaseController); //产生代理从而实现赋能
|
||||
@@ -114,8 +115,8 @@ public class FXControllerFactory {
|
||||
fxBaseController.setName(parent.getId());
|
||||
}
|
||||
ObservableMap namespace = fxmlLoader.getNamespace();
|
||||
addDataInNameSpace(namespace, fxBaseController);
|
||||
scanBind(namespace, fxBaseController);
|
||||
addDataInNameSpace(namespace, fxBaseController); //处理fxBaseController里面的@FXData
|
||||
scanBind(namespace, fxBaseController); //处理@FXBind
|
||||
register(fxBaseController, fxControllerProxy);
|
||||
} catch (IOException exception) {
|
||||
throw new RuntimeException(exception);
|
||||
@@ -136,28 +137,48 @@ public class FXControllerFactory {
|
||||
*/
|
||||
private static void register(FXBaseController fxBaseController, FXBaseController fxBaseControllerProxy) {
|
||||
FXPlusContext.addController(fxBaseController); //保存
|
||||
MessageQueue.getInstance().registerCosumer(fxBaseController, fxBaseControllerProxy); // 添加进入消息队列 信号功能
|
||||
MessageQueue.getInstance().registerConsumer(fxBaseController, fxBaseControllerProxy); // 添加进入消息队列 信号功能
|
||||
}
|
||||
|
||||
private static Stage createWindow(FXWindow fxWindow, FXBaseController fxControllerProxy) {
|
||||
/**
|
||||
* 为有FXWindow注解的类创建Stage
|
||||
*
|
||||
* @param fxWindow
|
||||
* @param fxBaseControllerProxy
|
||||
* @return
|
||||
*/
|
||||
private static Stage createWindow(FXWindow fxWindow, FXBaseController fxBaseControllerProxy) {
|
||||
Stage stage = new Stage();
|
||||
fxControllerProxy.setStage(stage);
|
||||
double preWidth = fxWindow.preWidth() == 0 ? fxControllerProxy.getPrefWidth() : fxWindow.preWidth();
|
||||
double preHeight = fxWindow.preHeight() == 0 ? fxControllerProxy.getPrefHeight() : fxWindow.preHeight();
|
||||
Scene scene = new Scene(fxControllerProxy, preWidth, preHeight);
|
||||
fxBaseControllerProxy.setStage(stage);
|
||||
double preWidth = fxWindow.preWidth() == 0 ? fxBaseControllerProxy.getPrefWidth() : fxWindow.preWidth();
|
||||
double preHeight = fxWindow.preHeight() == 0 ? fxBaseControllerProxy.getPrefHeight() : fxWindow.preHeight();
|
||||
Scene scene = new Scene(fxBaseControllerProxy, preWidth, preHeight);
|
||||
stage.setScene(scene);
|
||||
windowAnnotationParser.parse(stage, fxControllerProxy, fxWindow);
|
||||
stage.show();
|
||||
return stage;
|
||||
windowAnnotationParser.parse(stage, fxBaseControllerProxy, fxWindow);
|
||||
|
||||
StageManager.getInstance().registerWindow(fxBaseControllerProxy); //注册舞台
|
||||
if (fxWindow.mainStage() == true) { //当是主舞台时,先show为敬
|
||||
// System.out.println("FXControllerFactory: "+(fxControllerProxy.getStage() == null));
|
||||
fxBaseControllerProxy.showStage();
|
||||
}
|
||||
return stage;
|
||||
}
|
||||
|
||||
private FXControllerFactory() {
|
||||
|
||||
}
|
||||
|
||||
public static void loadMainStage(Class clazz, BeanBuilder beanBuilder) {
|
||||
/**
|
||||
* 加载舞台
|
||||
* 原函数名为loadMainStage(Class clazz, BeanBuilder beanBuilder)
|
||||
*
|
||||
* @param clazz
|
||||
* @param beanBuilder
|
||||
*/
|
||||
public static void loadStage(Class clazz, BeanBuilder beanBuilder) {
|
||||
FXWindow declaredAnnotation = (FXWindow) clazz.getDeclaredAnnotation(FXWindow.class);
|
||||
if ( declaredAnnotation != null && declaredAnnotation.mainStage() == true ) {
|
||||
//只有当用了FXWindow注解,才会注册Stage
|
||||
if (declaredAnnotation != null) {
|
||||
getFXWindow(clazz, null, beanBuilder);
|
||||
}
|
||||
}
|
||||
@@ -179,45 +200,50 @@ public class FXControllerFactory {
|
||||
FXBaseController fxBaseController = getFxBaseController(clazz, controllerName, beanBuilder);
|
||||
return fxBaseController;
|
||||
}
|
||||
public static Stage getFXWindow(Class clazz){
|
||||
|
||||
|
||||
public static Stage getFXWindow(Class clazz) {
|
||||
FXWindow fxWindow = (FXWindow) clazz.getDeclaredAnnotation(FXWindow.class);
|
||||
if(fxWindow !=null){
|
||||
if (fxWindow != null) {
|
||||
FXBaseController fxController = getFXController(clazz, null, BEAN_BUILDER);
|
||||
return createWindow(fxWindow, fxController);
|
||||
}else{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public static Stage getFXWindow(Class clazz, BeanBuilder beanBuilder) {
|
||||
FXWindow fxWindow = (FXWindow) clazz.getDeclaredAnnotation(FXWindow.class);
|
||||
if(fxWindow !=null){
|
||||
FXBaseController fxController = getFXController(clazz, null, beanBuilder);
|
||||
return createWindow(fxWindow, fxController);
|
||||
}else{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public static Stage getFXWindow(Class clazz, String controllerName) {
|
||||
FXWindow fxWindow = (FXWindow) clazz.getDeclaredAnnotation(FXWindow.class);
|
||||
if(fxWindow !=null){
|
||||
FXBaseController fxController = getFXController(clazz, controllerName, BEAN_BUILDER);
|
||||
return createWindow(fxWindow, fxController);
|
||||
}else{
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Stage getFXWindow(Class clazz, String controllerName, BeanBuilder beanBuilder){
|
||||
public static Stage getFXWindow(Class clazz, BeanBuilder beanBuilder) {
|
||||
FXWindow fxWindow = (FXWindow) clazz.getDeclaredAnnotation(FXWindow.class);
|
||||
if(fxWindow !=null){
|
||||
FXBaseController fxController = getFXController(clazz, controllerName, beanBuilder);
|
||||
if (fxWindow != null) {
|
||||
FXBaseController fxController = getFXController(clazz, null, beanBuilder);
|
||||
return createWindow(fxWindow, fxController);
|
||||
}else{
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
private static void parseData(Object object) {
|
||||
Class clazz = object.getClass();
|
||||
|
||||
public static Stage getFXWindow(Class clazz, String controllerName) {
|
||||
FXWindow fxWindow = (FXWindow) clazz.getDeclaredAnnotation(FXWindow.class);
|
||||
if (fxWindow != null) {
|
||||
FXBaseController fxController = getFXController(clazz, controllerName, BEAN_BUILDER);
|
||||
return createWindow(fxWindow, fxController);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Stage getFXWindow(Class clazz, String controllerName, BeanBuilder beanBuilder) {
|
||||
FXWindow fxWindow = (FXWindow) clazz.getDeclaredAnnotation(FXWindow.class);
|
||||
if (fxWindow != null) {
|
||||
FXBaseController fxController = getFXController(clazz, controllerName, beanBuilder);
|
||||
return createWindow(fxWindow, fxController);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void parseData(Object fxControllerObject) {
|
||||
Class clazz = fxControllerObject.getClass();
|
||||
Field[] fields = clazz.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
FXData annotation = field.getAnnotation(FXData.class);
|
||||
@@ -225,9 +251,9 @@ public class FXControllerFactory {
|
||||
field.setAccessible(true);
|
||||
//建立代理
|
||||
try {
|
||||
Object fieldValue = field.get(object);
|
||||
Object objectProxy = FXEntityFactory.warpFxBean(fieldValue);
|
||||
field.set(object, objectProxy);
|
||||
Object fieldValue = field.get(fxControllerObject);
|
||||
Object fieldValueProxy = FXEntityFactory.wrapFxBean(fieldValue);
|
||||
field.set(fxControllerObject, fieldValueProxy);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -270,7 +296,7 @@ public class FXControllerFactory {
|
||||
private static void parseBind(ObservableMap namespace, Object object, Field field) {
|
||||
FXBind fxBind = field.getAnnotation(FXBind.class);
|
||||
field.setAccessible(true);
|
||||
ExpressionParser expressionParser = new ExpressionParser(namespace,object);
|
||||
ExpressionParser expressionParser = new ExpressionParser(namespace, object);
|
||||
if (fxBind != null) {
|
||||
String[] expressions = fxBind.value();
|
||||
try {
|
||||
@@ -286,10 +312,10 @@ public class FXControllerFactory {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isFXWindow(Class clazz){
|
||||
if(clazz.getDeclaredAnnotation(FXWindow.class)!=null){
|
||||
private static boolean isFXWindow(Class clazz) {
|
||||
if (clazz.getDeclaredAnnotation(FXWindow.class) != null) {
|
||||
return true;
|
||||
}else{
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package cn.edu.scau.biubiusuisui.factory;
|
||||
|
||||
import cn.edu.scau.biubiusuisui.annotation.FXField;
|
||||
import cn.edu.scau.biubiusuisui.entity.FXFieldWarpper;
|
||||
import cn.edu.scau.biubiusuisui.entity.FXFieldWrapper;
|
||||
import cn.edu.scau.biubiusuisui.entity.FXPlusContext;
|
||||
import cn.edu.scau.biubiusuisui.proxy.FXEntityProxy;
|
||||
import cn.edu.scau.biubiusuisui.utils.ClassUtils;
|
||||
@@ -11,8 +11,8 @@ import javafx.collections.FXCollections;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author jack
|
||||
@@ -20,28 +20,29 @@ import java.util.List;
|
||||
*/
|
||||
public class FXEntityFactory {
|
||||
|
||||
private FXEntityFactory(){}
|
||||
|
||||
public static Object warpFxBean(Class clazz){
|
||||
return warpFxBean(clazz, new FXBuilder());
|
||||
private FXEntityFactory() {
|
||||
}
|
||||
|
||||
public static Object warpFxBean(Class clazz, BeanBuilder beanBuilder) {
|
||||
public static Object wrapFxBean(Class clazz) {
|
||||
return wrapFxBean(clazz, new FXBuilder());
|
||||
}
|
||||
|
||||
public static Object wrapFxBean(Class clazz, BeanBuilder beanBuilder) {
|
||||
Object object = null;
|
||||
object = beanBuilder.getBean(clazz);
|
||||
if(object !=null){
|
||||
return warpFxBean(object);
|
||||
}else {
|
||||
if (object != null) {
|
||||
return wrapFxBean(object);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Object warpFxBean(Object object){
|
||||
public static Object wrapFxBean(Object object) {
|
||||
FXEntityProxy fxEntityProxy = new FXEntityProxy();
|
||||
Object objectProxy = null;
|
||||
try {
|
||||
objectProxy = fxEntityProxy.getInstance(object);
|
||||
processFXEntityProxy(object,objectProxy,fxEntityProxy);
|
||||
objectProxy = fxEntityProxy.getInstance(object); // 初始化代理类
|
||||
processFXEntityProxy(object, objectProxy, fxEntityProxy);
|
||||
FXPlusContext.setProxyByBeanObject(objectProxy, fxEntityProxy);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
@@ -49,28 +50,27 @@ public class FXEntityFactory {
|
||||
return objectProxy;
|
||||
}
|
||||
|
||||
private static void processFXEntityProxy(Object entity, Object proxy,FXEntityProxy fxEntityProxy) throws IllegalAccessException {
|
||||
Map<String, FXFieldWarpper> fxFieldWarpperMap = new HashMap<>();
|
||||
Field []fields = entity.getClass().getDeclaredFields();
|
||||
for(Field field:fields){
|
||||
Annotation annotation = ClassUtils.getAnnotationInList( FXField.class,field.getDeclaredAnnotations());
|
||||
if(annotation != null){
|
||||
private static void processFXEntityProxy(Object entity, Object proxy, FXEntityProxy fxEntityProxy) throws IllegalAccessException {
|
||||
Map<String, FXFieldWrapper> fxFieldWrapperMap = new HashMap<>();
|
||||
Field[] fields = entity.getClass().getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
Annotation annotation = ClassUtils.getAnnotationInList(FXField.class, field.getDeclaredAnnotations());
|
||||
if (annotation != null) {
|
||||
Property property = null;
|
||||
field.setAccessible(true);
|
||||
FXField fxField = (FXField)annotation;
|
||||
FXFieldWarpper fieldWarpper = new FXFieldWarpper();
|
||||
fieldWarpper.setFxField(fxField);
|
||||
fieldWarpper.setType(field.getType());
|
||||
if(field.get(entity) == null){
|
||||
property = getFieldDefalutProperty(field);
|
||||
|
||||
}else{
|
||||
property = getFieldProperty(entity, field);
|
||||
FXField fxField = (FXField) annotation;
|
||||
FXFieldWrapper fieldWrapper = new FXFieldWrapper();
|
||||
fieldWrapper.setFxField(fxField);
|
||||
fieldWrapper.setType(field.getType());
|
||||
if (field.get(entity) == null) {
|
||||
property = getFieldDefalutProperty(field);
|
||||
} else {
|
||||
property = getFieldProperty(entity, field);
|
||||
}
|
||||
if(property !=null) {
|
||||
property.addListener((object,oldVal,newVal)->{
|
||||
if(!fxField.readOnly()) {
|
||||
if(!List.class.isAssignableFrom(field.getType())) {
|
||||
if (property != null) {
|
||||
property.addListener((object, oldVal, newVal) -> {
|
||||
if (!fxField.readOnly()) {
|
||||
if (!List.class.isAssignableFrom(field.getType())) {
|
||||
try {
|
||||
field.set(proxy, newVal);
|
||||
} catch (IllegalAccessException e) {
|
||||
@@ -80,63 +80,62 @@ public class FXEntityFactory {
|
||||
}
|
||||
});
|
||||
}
|
||||
fieldWarpper.setProperty(property);
|
||||
fxFieldWarpperMap.put(field.getName(), fieldWarpper);
|
||||
fieldWrapper.setProperty(property);
|
||||
fxFieldWrapperMap.put(field.getName(), fieldWrapper);
|
||||
}
|
||||
}
|
||||
fxEntityProxy.setFxFieldWarpperMap(fxFieldWarpperMap);
|
||||
fxEntityProxy.setFxFieldWrapperMap(fxFieldWrapperMap);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static Property getFieldProperty(Object object,Field field) throws IllegalAccessException {
|
||||
private static Property getFieldProperty(Object object, Field field) throws IllegalAccessException {
|
||||
Class type = field.getType();
|
||||
Object value = field.get(object);
|
||||
|
||||
Property property = null;
|
||||
|
||||
if(Boolean.class.equals(type) || boolean.class.equals(type)){
|
||||
if (Boolean.class.equals(type) || boolean.class.equals(type)) {
|
||||
property = new SimpleBooleanProperty((Boolean) value);
|
||||
}else if(Double.class.equals(type)||double.class.equals(type)){
|
||||
} else if (Double.class.equals(type) || double.class.equals(type)) {
|
||||
property = new SimpleDoubleProperty((Double) value);
|
||||
}else if (Float.class.equals(type) || float.class.equals(type)){
|
||||
} else if (Float.class.equals(type) || float.class.equals(type)) {
|
||||
property = new SimpleFloatProperty((Float) value);
|
||||
}else if(Integer.class.equals(type) || int.class.equals(type)){
|
||||
} 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(property)) {
|
||||
property = new SimpleLongProperty((Long) value);
|
||||
}else if(String.class.equals(type)){
|
||||
} else if (String.class.equals(type)) {
|
||||
property = new SimpleStringProperty((String) value);
|
||||
}else if(List.class.isAssignableFrom(type)){
|
||||
property = new SimpleListProperty(FXCollections.observableList((List)value));
|
||||
}else if(Object.class.isAssignableFrom(type)){
|
||||
} else if (List.class.isAssignableFrom(type)) {
|
||||
property = new SimpleListProperty(FXCollections.observableList((List) value));
|
||||
} else if (Object.class.isAssignableFrom(type)) {
|
||||
property = new SimpleObjectProperty(value);
|
||||
}
|
||||
return property;
|
||||
}
|
||||
private static Property getFieldDefalutProperty(Field field) throws IllegalAccessException{
|
||||
|
||||
private static Property getFieldDefalutProperty(Field field) throws IllegalAccessException {
|
||||
Class type = field.getType();
|
||||
Property property = null;
|
||||
if(Boolean.class.equals(type) || boolean.class.equals(type)){
|
||||
if (Boolean.class.equals(type) || boolean.class.equals(type)) {
|
||||
property = new SimpleBooleanProperty();
|
||||
}else if(Double.class.equals(type)||double.class.equals(type)){
|
||||
} else if (Double.class.equals(type) || double.class.equals(type)) {
|
||||
property = new SimpleDoubleProperty();
|
||||
}else if (Float.class.equals(type) || float.class.equals(type)){
|
||||
} else if (Float.class.equals(type) || float.class.equals(type)) {
|
||||
property = new SimpleFloatProperty();
|
||||
}else if(Integer.class.equals(type) || int.class.equals(type)){
|
||||
} 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(property)) {
|
||||
property = new SimpleLongProperty();
|
||||
}else if(String.class.equals(type)){
|
||||
} else if (String.class.equals(type)) {
|
||||
property = new SimpleStringProperty();
|
||||
}else if(List.class.isAssignableFrom(type)){
|
||||
} else if (List.class.isAssignableFrom(type)) {
|
||||
property = new SimpleListProperty();
|
||||
}else if(Object.class.isAssignableFrom(type)){
|
||||
} else if (Object.class.isAssignableFrom(type)) {
|
||||
property = new SimpleObjectProperty();
|
||||
}
|
||||
return property;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -11,17 +11,17 @@ import javafx.stage.Stage;
|
||||
*/
|
||||
public class FXWindowParser {
|
||||
|
||||
public void parse(Stage stage, Pane fxControllerProxy, FXWindow fxWindow){
|
||||
public void parse(Stage stage, Pane fxControllerProxy, FXWindow fxWindow) {
|
||||
|
||||
stage.setTitle(fxWindow.title());
|
||||
|
||||
if(fxWindow.resizable()){
|
||||
if (fxWindow.resizable()) {
|
||||
stage.setResizable(false);
|
||||
}
|
||||
|
||||
if(fxWindow.draggable()) {
|
||||
final int RESIZE_WIDTH = 5;// 判定是否为调整窗口状态的范围与边界距离
|
||||
EventHandler dragWindowHandler= new DragWindowHandlerImpl(stage,fxWindow.minWidth(),fxWindow.minHeight(),fxControllerProxy,fxWindow.resizable());
|
||||
if (fxWindow.draggable()) {
|
||||
final int RESIZE_WIDTH = 5;// 判定是否为调整窗口状态的范围与边界距离
|
||||
EventHandler dragWindowHandler = new DragWindowHandlerImpl(stage, fxWindow.minWidth(), fxWindow.minHeight(), fxControllerProxy, fxWindow.resizable());
|
||||
fxControllerProxy.setOnMousePressed(dragWindowHandler);
|
||||
fxControllerProxy.setOnMouseDragged(dragWindowHandler);
|
||||
fxControllerProxy.setOnMouseMoved(dragWindowHandler);
|
||||
|
||||
@@ -19,31 +19,32 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class MessageQueue {
|
||||
|
||||
|
||||
private static Map<String, List<FXMethodEntity>> receivers = new ConcurrentHashMap<>();
|
||||
private static Map<String, List<FXMethodEntity>> receivers = new ConcurrentHashMap<>(); //Map<主题,订阅了主题的所有方法>
|
||||
|
||||
private static MessageQueue messageQueue = null;
|
||||
|
||||
private MessageQueue(){ }
|
||||
private MessageQueue() {
|
||||
}
|
||||
|
||||
public static synchronized MessageQueue getInstance(){
|
||||
if(messageQueue == null){
|
||||
public static synchronized MessageQueue getInstance() {
|
||||
if (messageQueue == null) {
|
||||
messageQueue = new MessageQueue();
|
||||
}
|
||||
return messageQueue;
|
||||
}
|
||||
|
||||
public void registerCosumer(FXBaseController fxBaseController,FXBaseController fxBaseControllerProxy){
|
||||
public void registerConsumer(FXBaseController fxBaseController, FXBaseController fxBaseControllerProxy) {
|
||||
Class clazz = fxBaseController.getClass();
|
||||
Method [] methods = clazz.getDeclaredMethods();
|
||||
for(Method method : methods){
|
||||
Annotation[]annotations = method.getDeclaredAnnotations();
|
||||
for(Annotation annotation : annotations){
|
||||
if(FXReceiver.class.equals(annotation.annotationType())){
|
||||
FXReceiver receiver = (FXReceiver)annotation;
|
||||
FXMethodEntity fxMethodEntity = new FXMethodEntity(fxBaseControllerProxy,method);
|
||||
Method[] methods = clazz.getDeclaredMethods();
|
||||
for (Method method : methods) {
|
||||
Annotation[] annotations = method.getDeclaredAnnotations();
|
||||
for (Annotation annotation : annotations) {
|
||||
if (FXReceiver.class.equals(annotation.annotationType())) {
|
||||
// System.out.println("FXReceiver");
|
||||
FXReceiver receiver = (FXReceiver) annotation;
|
||||
FXMethodEntity fxMethodEntity = new FXMethodEntity(fxBaseControllerProxy, method);
|
||||
List<FXMethodEntity> fxMethodEntities = receivers.get(receiver.name());
|
||||
if(fxMethodEntities == null){
|
||||
if (fxMethodEntities == null) {
|
||||
fxMethodEntities = new ArrayList<>();
|
||||
}
|
||||
fxMethodEntities.add(fxMethodEntity);
|
||||
@@ -53,7 +54,7 @@ public class MessageQueue {
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMsg(String id,Object msg) {
|
||||
public void sendMsg(String id, Object msg) {
|
||||
List<FXMethodEntity> lists = receivers.get(id);
|
||||
if (lists != null) {
|
||||
for (FXMethodEntity fxMethodEntity : lists) {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package cn.edu.scau.biubiusuisui.proxy;
|
||||
|
||||
import cn.edu.scau.biubiusuisui.annotation.FXRedirect;
|
||||
import cn.edu.scau.biubiusuisui.annotation.FXSender;
|
||||
import cn.edu.scau.biubiusuisui.entity.FXBaseController;
|
||||
import cn.edu.scau.biubiusuisui.messageQueue.MessageQueue;
|
||||
import net.sf.cglib.beans.BeanCopier;
|
||||
import cn.edu.scau.biubiusuisui.stage.StageManager;
|
||||
import net.sf.cglib.proxy.Enhancer;
|
||||
import net.sf.cglib.proxy.MethodInterceptor;
|
||||
import net.sf.cglib.proxy.MethodProxy;
|
||||
@@ -13,7 +14,6 @@ import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
*
|
||||
* This proxy class intercept Methods that has special annotation such as
|
||||
* FXSender which is a mark for message queue
|
||||
*
|
||||
@@ -26,9 +26,9 @@ public class FXControllerProxy implements MethodInterceptor {
|
||||
FXBaseController target;
|
||||
|
||||
|
||||
|
||||
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);
|
||||
@@ -40,26 +40,34 @@ public class FXControllerProxy implements MethodInterceptor {
|
||||
|
||||
@Override
|
||||
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
|
||||
Object o1 = methodProxy.invokeSuper(o, objects);
|
||||
Annotation []annotations = method.getDeclaredAnnotations();
|
||||
for(Annotation annotation : annotations){
|
||||
if(FXSender.class.equals(annotation.annotationType())){
|
||||
FXSender fxSender = (FXSender)annotation;
|
||||
String name = target.getName() +":";
|
||||
if("".equals(fxSender.name())){
|
||||
name += method.getName();
|
||||
}else{
|
||||
name += fxSender.name();
|
||||
Object o1 = methodProxy.invokeSuper(o, objects); //获取该方法运行后的结果
|
||||
Annotation[] annotations = method.getDeclaredAnnotations();
|
||||
|
||||
for (Annotation annotation : annotations) {
|
||||
if (FXSender.class.equals(annotation.annotationType())) { // 拦截是否发送消息函数
|
||||
FXSender fxSender = (FXSender) annotation;
|
||||
// System.out.println("FXSender");
|
||||
String name = target.getName() + ":";
|
||||
// System.out.println("FXControllerProxy:" + name);
|
||||
if ("".equals(fxSender.name())) {
|
||||
name += method.getName();
|
||||
} else {
|
||||
name += fxSender.name();
|
||||
}
|
||||
MessageQueue.getInstance().sendMsg(name,o1);
|
||||
MessageQueue.getInstance().sendMsg(name, o1);
|
||||
}
|
||||
if (FXRedirect.class.equals((annotation.annotationType()))) { //拦截是否重定向函数
|
||||
FXRedirect fxRedirect = (FXRedirect) annotation;
|
||||
if (fxRedirect.close()) { //关闭原窗口
|
||||
StageManager.getInstance().closeStage(target.getName());
|
||||
}
|
||||
StageManager.getInstance().redirectTo(o1);
|
||||
}
|
||||
}
|
||||
return o1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void inject(Object target,Object proxy){
|
||||
private void inject(Object target, Object proxy) {
|
||||
Class clazz = target.getClass();
|
||||
Field[] fields = clazz.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package cn.edu.scau.biubiusuisui.proxy;
|
||||
|
||||
import cn.edu.scau.biubiusuisui.entity.FXFieldWarpper;
|
||||
import cn.edu.scau.biubiusuisui.entity.FXFieldWrapper;
|
||||
import cn.edu.scau.biubiusuisui.utils.StringUtils;
|
||||
import javafx.beans.property.*;
|
||||
import net.sf.cglib.proxy.Enhancer;
|
||||
@@ -17,7 +17,7 @@ import java.util.Map;
|
||||
public class FXEntityProxy implements MethodInterceptor {
|
||||
|
||||
Object target;
|
||||
private Map<String, FXFieldWarpper> fxFieldWarpperMap;
|
||||
private Map<String, FXFieldWrapper> fxFieldWrapperMap;
|
||||
|
||||
public Object getInstance(Object target) {
|
||||
this.target = target;
|
||||
@@ -39,20 +39,20 @@ public class FXEntityProxy implements MethodInterceptor {
|
||||
*/
|
||||
@Override
|
||||
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
|
||||
Object o1 = methodProxy.invokeSuper(o, objects);
|
||||
Object o1 = methodProxy.invokeSuper(o, objects); //获取该方法运行后的结果
|
||||
String methodName = method.getName();
|
||||
String fieldName = null;
|
||||
if (methodName.length() >= 3) {
|
||||
fieldName = StringUtils.toInstanceName(methodName.substring(3));
|
||||
fieldName = StringUtils.toInstanceName(methodName.substring(3)); // 该method有可能是getter和setter方法,进行处理
|
||||
} else {
|
||||
return o1;
|
||||
}
|
||||
FXFieldWarpper fxFieldWarpper = fxFieldWarpperMap.get(fieldName);
|
||||
FXFieldWrapper fxFieldWrapper = fxFieldWrapperMap.get(fieldName);
|
||||
Property property = getPropertyByFieldName(fieldName);
|
||||
if(fxFieldWarpper == null || property == null){
|
||||
if (fxFieldWrapper == null || property == null) {
|
||||
return o1;
|
||||
}
|
||||
Class type = fxFieldWarpper.getType();
|
||||
Class type = fxFieldWrapper.getType();
|
||||
if (methodName.startsWith("set")) {
|
||||
if(Boolean.class.equals(type) || boolean.class.equals(type)){
|
||||
((SimpleBooleanProperty)property).set((Boolean)objects[0]);
|
||||
@@ -86,17 +86,17 @@ public class FXEntityProxy implements MethodInterceptor {
|
||||
}
|
||||
|
||||
public Property getPropertyByFieldName(String name) {
|
||||
if(fxFieldWarpperMap.get(name) ==null){
|
||||
if (fxFieldWrapperMap.get(name) == null) {
|
||||
return null;
|
||||
}
|
||||
return fxFieldWarpperMap.get(name).getProperty() ;
|
||||
return fxFieldWrapperMap.get(name).getProperty();
|
||||
}
|
||||
|
||||
public Map<String, FXFieldWarpper> getFxFieldWarpperMap() {
|
||||
return fxFieldWarpperMap;
|
||||
public Map<String, FXFieldWrapper> getFxFieldWrapperMap() {
|
||||
return fxFieldWrapperMap;
|
||||
}
|
||||
|
||||
public void setFxFieldWarpperMap(Map<String, FXFieldWarpper> fxFieldWarpperMap) {
|
||||
this.fxFieldWarpperMap = fxFieldWarpperMap;
|
||||
public void setFxFieldWrapperMap(Map<String, FXFieldWrapper> fxFieldWrapperMap) {
|
||||
this.fxFieldWrapperMap = fxFieldWrapperMap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package cn.edu.scau.biubiusuisui.stage;
|
||||
|
||||
import cn.edu.scau.biubiusuisui.entity.FXBaseController;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @author suiyu_yang
|
||||
* @description 舞台管理器
|
||||
* @date 2019/12/3 15:43
|
||||
* @email suiyu_yang@163.com
|
||||
*/
|
||||
public class StageManager {
|
||||
private static StageManager stageManager = null;
|
||||
private static Map<String, FXBaseController> windows = new ConcurrentHashMap<>(); //
|
||||
|
||||
private StageManager() {
|
||||
|
||||
}
|
||||
|
||||
public static synchronized StageManager getInstance() {
|
||||
if (stageManager == null) {
|
||||
stageManager = new StageManager();
|
||||
}
|
||||
return stageManager;
|
||||
}
|
||||
|
||||
public void registerWindow(FXBaseController fxBaseControllerProxy) {
|
||||
if (fxBaseControllerProxy.isWindow()) {
|
||||
// System.out.println("StageController: "+(fxBaseControllerProxy.getStage() == null));
|
||||
windows.put(fxBaseControllerProxy.getName(), fxBaseControllerProxy);
|
||||
}
|
||||
}
|
||||
|
||||
public void closeStage(String controllerName) {
|
||||
windows.get(controllerName).closeStage();
|
||||
}
|
||||
|
||||
public void redirectTo(Object controller) {
|
||||
System.out.println("跳转->" + controller);
|
||||
windows.get(controller).showStage();
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,6 @@ public class BeanUtil {
|
||||
if(fxEntityProxy == null){
|
||||
return null;
|
||||
}
|
||||
return fxEntityProxy.getFxFieldWarpperMap().get(fieldName).getProperty();
|
||||
return fxEntityProxy.getFxFieldWrapperMap().get(fieldName).getProperty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,22 +13,22 @@ import java.util.List;
|
||||
* @Date:2019/6/25 5:20
|
||||
*/
|
||||
public class ClassUtils {
|
||||
private ClassLoader cl;
|
||||
private ClassLoader classLoader;
|
||||
|
||||
public ClassUtils() {
|
||||
cl = getClass().getClassLoader();
|
||||
classLoader = getClass().getClassLoader();
|
||||
}
|
||||
|
||||
private List<String> getAllFXControllerClassName(String base, List<String> nameList) {
|
||||
String splashPath = StringUtils.dotToSplash(base);
|
||||
URL url = cl.getResource(splashPath);
|
||||
URL url = classLoader.getResource(splashPath);
|
||||
String filePath = StringUtils.getRootPath(url);
|
||||
List<String> names = null;
|
||||
names = readFromDirectory(filePath);
|
||||
for (String name : names) {
|
||||
if (isClassFile(name)) {
|
||||
nameList.add(toFullyQualifiedName(name, base));
|
||||
} else if (isDirectory(name)){
|
||||
} else if (isDirectory(name)) {
|
||||
nameList = getAllFXControllerClassName(base + "." + name, nameList);
|
||||
}
|
||||
}
|
||||
@@ -49,9 +49,11 @@ public class ClassUtils {
|
||||
private static boolean isClassFile(String name) {
|
||||
return name.endsWith(".class");
|
||||
}
|
||||
private static boolean isDirectory(String name){
|
||||
|
||||
private static boolean isDirectory(String name) {
|
||||
return !name.contains(".");
|
||||
}
|
||||
|
||||
private static List<String> readFromDirectory(String path) {
|
||||
File file = new File(path);
|
||||
String[] names = file.list();
|
||||
@@ -63,8 +65,8 @@ public class ClassUtils {
|
||||
}
|
||||
|
||||
|
||||
public static boolean hasDeclaredAnnotation(Class clazz, Class annotation){
|
||||
if(annotation == null){
|
||||
public static boolean hasDeclaredAnnotation(Class clazz, Class annotation) {
|
||||
if (annotation == null) {
|
||||
return false;
|
||||
}
|
||||
if (hasAnnotationInList(annotation, clazz.getDeclaredAnnotations())) return true;
|
||||
@@ -72,7 +74,7 @@ public class ClassUtils {
|
||||
}
|
||||
|
||||
public static boolean hasAnnotation(Class clazz, Class annotation) {
|
||||
if(annotation == null){
|
||||
if (annotation == null) {
|
||||
return false;
|
||||
}
|
||||
if (hasAnnotationInList(annotation, clazz.getAnnotations())) return true;
|
||||
@@ -80,16 +82,16 @@ public class ClassUtils {
|
||||
}
|
||||
|
||||
public static boolean hasAnnotationInList(Class annotation, Annotation[] annotations2) {
|
||||
if(getAnnotationInList(annotation,annotations2) == null){
|
||||
if (getAnnotationInList(annotation, annotations2) == null) {
|
||||
return false;
|
||||
}else{
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static Annotation getAnnotationInList(Class annotation,Annotation[]annotations){
|
||||
if(annotations == null || annotation == null){
|
||||
return null;
|
||||
public static Annotation getAnnotationInList(Class annotation, Annotation[] annotations) {
|
||||
if (annotations == null || annotation == null) {
|
||||
return null;
|
||||
}
|
||||
for (Annotation annotation1 : annotations) {
|
||||
if (annotation1.annotationType().equals(annotation)) {
|
||||
@@ -99,11 +101,11 @@ public class ClassUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void copyField(Object target,Object base){
|
||||
public static void copyField(Object target, Object base) {
|
||||
Class clazz = base.getClass();
|
||||
Class targetClass = target.getClass();
|
||||
Field []fields = clazz.getDeclaredFields();
|
||||
for(Field field:fields){
|
||||
Field[] fields = clazz.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
field.setAccessible(true);
|
||||
|
||||
// Field field1 = targetClass.getField(field.getName());
|
||||
|
||||
@@ -4,6 +4,7 @@ package cn.edu.scau.biubiusuisui.utils;
|
||||
* @Author jack
|
||||
* @Date:2019/6/25 3:46
|
||||
*/
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
public class StringUtils {
|
||||
@@ -61,21 +62,34 @@ public class StringUtils {
|
||||
return trimmed.substring(splashIndex);
|
||||
}
|
||||
|
||||
public static String getBaseClassName(String name){
|
||||
public static String getBaseClassName(String name) {
|
||||
int index = name.indexOf("$");
|
||||
if(index == -1){
|
||||
if (index == -1) {
|
||||
return name;
|
||||
}
|
||||
return name.substring(0,index);
|
||||
// System.out.println(name.substring(0,index));
|
||||
return name.substring(0, index);
|
||||
}
|
||||
|
||||
|
||||
public static String toInstanceName(String name){
|
||||
/**
|
||||
* Object -> object ; Student -> student
|
||||
*
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
public static String toInstanceName(String name) {
|
||||
String result = name.substring(0, 1).toLowerCase().concat(name.substring(1));
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String toClassName(String name){
|
||||
/**
|
||||
* object -> Object ; student -> Student
|
||||
*
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
public static String toClassName(String name) {
|
||||
String result = name.substring(0, 1).toUpperCase().concat(name.substring(1));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.TextField?>
|
||||
<?import javafx.scene.layout.Pane?>
|
||||
|
||||
<fx:root prefHeight="191.0" prefWidth="607.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.actionDemo.MainController">
|
||||
<children>
|
||||
<TextField fx:id="time" layoutX="108.0" layoutY="28.0" prefHeight="28.0" prefWidth="330.0" />
|
||||
<Label fx:id="us" layoutX="108.0" layoutY="75.0" prefHeight="24.0" prefWidth="330.0" text="US:" />
|
||||
<Label fx:id="jp" layoutX="108.0" layoutY="107.0" prefHeight="24.0" prefWidth="330.0" text="JP:" />
|
||||
<Label fx:id="uk" layoutX="108.0" layoutY="142.0" prefHeight="24.0" prefWidth="330.0" text="UK:" />
|
||||
<Label layoutX="67.0" layoutY="77.0" text="US" />
|
||||
<Label layoutX="69.0" layoutY="109.0" text="JP" />
|
||||
<Label layoutX="66.0" layoutY="144.0" text="UK" />
|
||||
</children>
|
||||
</fx:root>
|
||||
16
src/main/resources/actionDemo/actionDemo.fxml
Normal file
16
src/main/resources/actionDemo/actionDemo.fxml
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.Pane?>
|
||||
<fx:root prefHeight="191.0" prefWidth="607.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.actionDemo.MainController">
|
||||
<children>
|
||||
<TextField fx:id="time" layoutX="108.0" layoutY="28.0" prefHeight="28.0" prefWidth="330.0"/>
|
||||
<Label fx:id="us" layoutX="108.0" layoutY="75.0" prefHeight="24.0" prefWidth="330.0" text="US:"/>
|
||||
<Label fx:id="jp" layoutX="108.0" layoutY="107.0" prefHeight="24.0" prefWidth="330.0" text="JP:"/>
|
||||
<Label fx:id="uk" layoutX="108.0" layoutY="142.0" prefHeight="24.0" prefWidth="330.0" text="UK:"/>
|
||||
<Label layoutX="67.0" layoutY="77.0" text="US"/>
|
||||
<Label layoutX="69.0" layoutY="109.0" text="JP"/>
|
||||
<Label layoutX="66.0" layoutY="144.0" text="UK"/>
|
||||
</children>
|
||||
</fx:root>
|
||||
@@ -3,10 +3,9 @@
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.ListView?>
|
||||
<?import javafx.scene.layout.Pane?>
|
||||
|
||||
<fx:root prefHeight="600.0" 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.listDemo.MainController">
|
||||
<children>
|
||||
<ListView fx:id="list" layoutX="32.0" layoutY="62.0" prefHeight="489.0" prefWidth="728.0" />
|
||||
<Button layoutX="691.0" layoutY="564.0" mnemonicParsing="false" onAction="#addName" text="Button" />
|
||||
</children>
|
||||
<children>
|
||||
<ListView fx:id="userNameListView" layoutX="144.0" layoutY="46.0" prefHeight="457.0" prefWidth="423.0"/>
|
||||
<Button layoutX="602.0" layoutY="489.0" mnemonicParsing="false" onAction="#addUserName" text="addUserName"/>
|
||||
</children>
|
||||
</fx:root>
|
||||
18
src/main/resources/mqDemo/main.fxml
Normal file
18
src/main/resources/mqDemo/main.fxml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import cn.edu.scau.biubiusuisui.example.mqDemo.TopBarController?>
|
||||
<?import javafx.scene.control.TextArea?>
|
||||
<?import javafx.scene.layout.Pane?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<fx:root maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0"
|
||||
prefWidth="600.0" type="Pane" xmlns="http://javafx.com/javafx/10.0.2-internal"
|
||||
xmlns:fx="http://javafx.com/fxml/1" fx:controller="cn.edu.scau.biubiusuisui.example.mqDemo.MainController">
|
||||
<children>
|
||||
<VBox prefHeight="400.0" prefWidth="600.0">
|
||||
<children>
|
||||
<TopBarController/>
|
||||
<TextArea fx:id="outTA" editable="false" prefHeight="350.0" prefWidth="600.0" wrapText="true"/>
|
||||
</children>
|
||||
</VBox>
|
||||
</children>
|
||||
</fx:root>
|
||||
20
src/main/resources/mqDemo/topBar.fxml
Normal file
20
src/main/resources/mqDemo/topBar.fxml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.Pane?>
|
||||
<fx:root maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="50.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.mqDemo.TopBarController">
|
||||
<children>
|
||||
<HBox alignment="CENTER" prefHeight="50.0" prefWidth="600.0" spacing="20.0">
|
||||
<children>
|
||||
<Button mnemonicParsing="false" onAction="#indexClick" prefHeight="50.0" prefWidth="100.0" text="首页"/>
|
||||
<Button mnemonicParsing="false" onAction="#scoreClick" prefHeight="50.0" prefWidth="100.0" text="积分中心"/>
|
||||
<Button mnemonicParsing="false" onAction="#questionClick" prefHeight="50.0" prefWidth="100.0"
|
||||
text="问答中心"/>
|
||||
<Button mnemonicParsing="false" onAction="#selfClick" prefHeight="50.0" prefWidth="100.0" text="个人中心"/>
|
||||
</children>
|
||||
</HBox>
|
||||
</children>
|
||||
</fx:root>
|
||||
16
src/main/resources/redirectDemo/dialog.fxml
Normal file
16
src/main/resources/redirectDemo/dialog.fxml
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.layout.Pane?>
|
||||
<?import javafx.scene.text.Font?>
|
||||
<fx:root maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0"
|
||||
prefWidth="400.0" type="Pane" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1">
|
||||
<children>
|
||||
<Label layoutX="103.0" layoutY="100.0" text="这是一个弹窗......">
|
||||
<font>
|
||||
<Font size="24.0"/>
|
||||
</font>
|
||||
</Label>
|
||||
</children>
|
||||
</fx:root>
|
||||
51
src/main/resources/redirectDemo/login.fxml
Normal file
51
src/main/resources/redirectDemo/login.fxml
Normal file
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import javafx.scene.text.Font?>
|
||||
<fx:root maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0"
|
||||
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">
|
||||
<children>
|
||||
<Label alignment="CENTER" prefHeight="50.0" prefWidth="250.0" text="登录">
|
||||
<font>
|
||||
<Font size="27.0"/>
|
||||
</font>
|
||||
</Label>
|
||||
<HBox alignment="CENTER" prefHeight="50.0" prefWidth="200.0">
|
||||
<children>
|
||||
<Label alignment="CENTER" prefHeight="50.0" prefWidth="50.0" text="用户名:"/>
|
||||
<TextField fx:id="usernameTF"/>
|
||||
</children>
|
||||
</HBox>
|
||||
<HBox alignment="CENTER" prefHeight="50.0" prefWidth="200.0">
|
||||
<children>
|
||||
<Label alignment="CENTER" prefHeight="50.0" prefWidth="50.0" text="密码:"/>
|
||||
<PasswordField fx:id="passwordPF"/>
|
||||
</children>
|
||||
</HBox>
|
||||
<HBox alignment="CENTER_RIGHT" prefHeight="50.0" prefWidth="200.0">
|
||||
<children>
|
||||
<Label onMouseClicked="#registerClick" prefHeight="50.0" text="还没有账户,去注册" underline="true">
|
||||
<HBox.margin>
|
||||
<Insets right="10.0"/>
|
||||
</HBox.margin>
|
||||
</Label>
|
||||
</children>
|
||||
</HBox>
|
||||
<HBox alignment="CENTER_RIGHT" prefHeight="50.0" prefWidth="200.0">
|
||||
<children>
|
||||
<Button mnemonicParsing="false" onAction="#redirectToDialog" text="测试弹窗的按钮">
|
||||
<HBox.margin>
|
||||
<Insets right="20.0"/>
|
||||
</HBox.margin>
|
||||
</Button>
|
||||
</children>
|
||||
</HBox>
|
||||
</children>
|
||||
</VBox>
|
||||
</children>
|
||||
</fx:root>
|
||||
8
src/main/resources/redirectDemo/register.css
Normal file
8
src/main/resources/redirectDemo/register.css
Normal file
@@ -0,0 +1,8 @@
|
||||
#content {
|
||||
alignment: center;
|
||||
}
|
||||
|
||||
#content .label {
|
||||
-fx-pref-height: 50;
|
||||
-fx-pref-width: 100;
|
||||
}
|
||||
69
src/main/resources/redirectDemo/register.fxml
Normal file
69
src/main/resources/redirectDemo/register.fxml
Normal file
@@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import javafx.scene.text.Font?>
|
||||
<fx:root maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="500.0"
|
||||
prefWidth="600.0" stylesheets="@register.css" 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.RegisterController">
|
||||
<children>
|
||||
<VBox alignment="CENTER" layoutX="100.0" layoutY="55.0" prefHeight="350.0" prefWidth="400.0">
|
||||
<children>
|
||||
<HBox prefHeight="50.0" prefWidth="200.0">
|
||||
<children>
|
||||
<Label alignment="CENTER" prefHeight="50.0" prefWidth="404.0" text="注册">
|
||||
<font>
|
||||
<Font size="24.0"/>
|
||||
</font>
|
||||
</Label>
|
||||
</children>
|
||||
</HBox>
|
||||
<VBox id="content" alignment="CENTER" prefHeight="350.0" prefWidth="400.0">
|
||||
<children>
|
||||
<HBox alignment="CENTER" prefHeight="50.0" prefWidth="200.0">
|
||||
<children>
|
||||
<Label text="用户名:"/>
|
||||
<TextField fx:id="usernameTF"/>
|
||||
</children>
|
||||
</HBox>
|
||||
<HBox alignment="CENTER" prefHeight="50.0" prefWidth="200.0">
|
||||
<children>
|
||||
<Label text="电子邮箱:"/>
|
||||
<TextField fx:id="emailTF"/>
|
||||
</children>
|
||||
</HBox>
|
||||
<HBox alignment="CENTER" prefHeight="50.0" prefWidth="200.0">
|
||||
<children>
|
||||
<Label text="密码:"/>
|
||||
<PasswordField fx:id="passwordPF"/>
|
||||
</children>
|
||||
</HBox>
|
||||
<HBox alignment="CENTER" prefHeight="50.0" prefWidth="200.0">
|
||||
<children>
|
||||
<Label text="确认密码:"/>
|
||||
<PasswordField fx:id="confirmPasswordPF"/>
|
||||
</children>
|
||||
</HBox>
|
||||
<HBox alignment="CENTER_RIGHT" prefHeight="50.0" prefWidth="200.0">
|
||||
<children>
|
||||
<Label minWidth="150.0" onMouseClicked="#loginClick" prefWidth="151.0" text="已有账号,前往登录"
|
||||
underline="true"/>
|
||||
</children>
|
||||
</HBox>
|
||||
<HBox alignment="CENTER_RIGHT" prefHeight="50.0" prefWidth="200.0">
|
||||
<children>
|
||||
<Button mnemonicParsing="false" onAction="#registerClick" text="注册">
|
||||
<HBox.margin>
|
||||
<Insets right="50.0"/>
|
||||
</HBox.margin>
|
||||
</Button>
|
||||
</children>
|
||||
</HBox>
|
||||
</children>
|
||||
</VBox>
|
||||
</children>
|
||||
</VBox>
|
||||
</children>
|
||||
</fx:root>
|
||||
33
src/main/resources/redirectDemo/success.fxml
Normal file
33
src/main/resources/redirectDemo/success.fxml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?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="登录成功">
|
||||
<font>
|
||||
<Font size="27.0"/>
|
||||
</font>
|
||||
</Label>
|
||||
<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"/>
|
||||
</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"/>
|
||||
</children>
|
||||
</HBox>
|
||||
</children>
|
||||
</VBox>
|
||||
<Button layoutX="421.0" layoutY="367.0" mnemonicParsing="false" onAction="#redirectToLogin" text="返回主界面"/>
|
||||
</children>
|
||||
</fx:root>
|
||||
Reference in New Issue
Block a user