diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml index d2b0f25..39adbfa 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -15,7 +15,7 @@ \ No newline at end of file diff --git a/.idea/dictionaries/suisui.xml b/.idea/dictionaries/suisui.xml new file mode 100644 index 0000000..de57ddd --- /dev/null +++ b/.idea/dictionaries/suisui.xml @@ -0,0 +1,8 @@ + + + + biubiusuisui + scau + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 7855ba6..bab5fb5 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -6,34 +6,65 @@ - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - + - + - + + + + + - + + - + + + + + - - + + + + + + + - + - - @@ -818,6 +347,10 @@ + + + + 1561745555309 @@ -903,9 +436,6 @@ - - @@ -915,96 +445,19 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -1040,109 +496,92 @@ file://$PROJECT_DIR$/src/main/java/cn/edu/scau/biubiusuisui/config/FXMLLoaderPlus.java 2569 - jar://C:/java/jdk/javafx-src.zip!/com/sun/javafx/fxml/expression/ExpressionValue.java 201 - file://$PROJECT_DIR$/src/main/java/cn/edu/scau/biubiusuisui/expression/data/MyBeanAdapter.java 12 - jar://C:/java/jdk/javafx-src.zip!/com/sun/javafx/fxml/expression/ExpressionValue.java 46 - jar://C:/java/jdk/javafx-src.zip!/com/sun/javafx/fxml/expression/ExpressionValue.java 103 - jar://C:/java/jdk/javafx-src.zip!/com/sun/javafx/fxml/expression/ExpressionValue.java 130 - jar://C:/java/jdk/javafx-src.zip!/com/sun/javafx/fxml/expression/ExpressionValue.java 104 - jar://C:/java/jdk/javafx-src.zip!/javafx/beans/property/StringPropertyBase.java 161 - file://$PROJECT_DIR$/src/main/java/cn/edu/scau/biubiusuisui/expression/data/MyExpressionValue.java 100 - file://$PROJECT_DIR$/src/main/java/cn/edu/scau/biubiusuisui/proxy/FXControllerProxy.java - 74 - + 82 jar://$MAVEN_REPOSITORY$/cglib/cglib/3.1/cglib-3.1.jar!/net/sf/cglib/beans/BeanCopier.class 126 - file://$PROJECT_DIR$/src/main/java/cn/edu/scau/biubiusuisui/expression/data/ExpressionParser.java 112 - file://$PROJECT_DIR$/src/main/java/cn/edu/scau/biubiusuisui/expression/data/ExpressionParser.java 168 - jar://C:/java/jdk/javafx-src.zip!/com/sun/javafx/fxml/expression/BinaryExpression.java 54 - jar://C:/java/jdk/javafx-src.zip!/com/sun/javafx/fxml/expression/BinaryExpression.java 74 - jar://C:/java/jdk/javafx-src.zip!/com/sun/javafx/fxml/expression/BinaryExpression.java 75 - file://$PROJECT_DIR$/src/main/java/cn/edu/scau/biubiusuisui/proxy/FXEntityProxy.java 70 - jar://C:/java/jdk/javafx-src.zip!/com/sun/javafx/fxml/expression/BinaryExpression.java 53 - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/README.md b/README.md index 032d930..c729e27 100644 --- a/README.md +++ b/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项目开发、为了减少项目之间组件耦合而打造的框架。目前框架主要功能如下图所示: -![输入图片说明](https://images.gitee.com/uploads/images/2019/0629/155142_1235eb9c_2067650.png "JavaFX-Plus.png") +![输入图片说明](doc/JavaFx-Plus.png) ### 开发进程 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 @@ -49,51 +59,130 @@ ``` -## 特色 +## 框架功能描述 + +### 模块化开发 + +#### 介绍 + +在Java开发过程中很多界面是相似或者重复的,如果能够将这些界面打包成为一个自定义控件,并且通过Scenebuilder拖动就能产生一个控件那将会大大提高我们的开发效率。所以我们提出将不同区域划分为不同的子模块,已达到减少耦合和加速并行开发。一般我们经常把界面分为顶部工具栏,左边导航栏,右侧的内容栏,如果全部内容都写在一个Controller那么将会导致十分臃肿,我们希望将不同的区域划分开来分而治之。 + +#### 如何创建模块 + +只要新建一个类继承自FXBaseController,而FXBaseController是继承于Pane,这就是JavaFX-Plus的设计思想之一切皆为Pane。在类上标上FXController注解,提供FXML文件的地址。如果设置为FXWindow那么将会把这个Controller以单独的Window显示,这里仅仅几句代码就实现了一个简单的窗口程序。 + +![输入图片说明](https://images.gitee.com/uploads/images/2019/0629/022014_83ecdbde_2067650.png "controllerConfig.png") + +图2 Controller配置 + +![输入图片说明](https://images.gitee.com/uploads/images/2019/0629/022024_71892db3_2067650.png "demo1.png") + +图3 显示结果 + +#### scenebuilder中导入刚刚生成的上面的控件 + +![输入图片说明](https://images.gitee.com/uploads/images/2019/0629/022036_e128f313_2067650.gif "modulesAction.gif") + +图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 - } - } ``` -![输入图片说明](https://images.gitee.com/uploads/images/2019/0629/022051_db8dbc7a_2067650.gif "signalshow.gif") -### 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"); + } +} +``` + +![输入图片说明](doc/mqDemo/20191208-194336-signalshow.gif) + +### 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 { ![输入图片说明](https://images.gitee.com/uploads/images/2019/0630/135637_cb0e0a89_2067650.gif "resizeAble.gif") -### 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 { 如图所示: ![输入图片说明](https://images.gitee.com/uploads/images/2019/0724/231705_976181ba_2067650.gif "expression.gif") + + #### View和View绑定 + ```java @FXBind("text=${psw.text}") @FXML @@ -281,62 +358,273 @@ private Label pswMsg;//任何psw中的内容都会同步到pswMsg中 如图所示 ![输入图片说明](https://images.gitee.com/uploads/images/2019/0724/232237_7e243f15_2067650.gif "expressionV2V.gif") -### 模块化开发 + + +#### 函数表达式绑定 + +示例代码可见`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. 动态演示 + +如图所示: + +![20191210-175409-actionDemo](doc/actionDemo/20191210-175409-actionDemo.gif) + +### 多窗口切换功能 #### 介绍 -在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`只能标记这是一个控件。 -![输入图片说明](https://images.gitee.com/uploads/images/2019/0629/022014_83ecdbde_2067650.png "controllerConfig.png") +`@FXWindow`:标记于类上,标记这个Controller需要以窗口显示,只有需要以单独窗口显示时才会被重定向。 -图2 Controller配置 +`@FXRedirect`:标记于函数上,标记该函数用于处理重定向。 -![输入图片说明](https://images.gitee.com/uploads/images/2019/0629/022024_71892db3_2067650.png "demo1.png") +#### 规定 -图3 显示结果 +本框架规定,当需要使用`@FXRedirect`标记函数处理重定向时,函数必须是返回String类型的函数,且返回已注册的Controller名,如需要重定向至登录成功界面,控制器为`SuccessController`,则需要写上`return "SuccessController"。 -#### scenebuilder中导入刚刚生成的上面的控件 +#### 使用方法 -![输入图片说明](https://images.gitee.com/uploads/images/2019/0629/022036_e128f313_2067650.gif "modulesAction.gif") +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. 跳转至另一个窗口(关闭原窗口) + +![](doc/redirectDemo/20191208-125739-close.gif) + +2. 弹窗形式弹出窗口(不关闭原窗口) + +![](doc/redirectDemo/20191208-125511-not close.gif) + +#### 不足之处 + +暂未实现携带数据的窗口跳转,目前只实现纯粹跳转到另一个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> controllerContext = new ConcurrentHashMap<>(); //FXController控制器注册表 + + private static Map beanMap = new ConcurrentHashMap<>(); // Object注册为FXEntityObject + + + public static void addController(FXBaseController fxBaseController){ + List controllers = controllerContext.get(fxBaseController.getName()); + if(controllers == null){ + controllers = new LinkedList<>(); + } + controllers.add(fxBaseController); + } + + public static List 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 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文件的根标签必须为``。 + ```xml diff --git a/doc/JavaFX-Plus.png b/doc/JavaFX-Plus.png new file mode 100644 index 0000000..72c861c Binary files /dev/null and b/doc/JavaFX-Plus.png differ diff --git a/doc/actionDemo/20191210-175409-actionDemo.gif b/doc/actionDemo/20191210-175409-actionDemo.gif new file mode 100644 index 0000000..3b2dd30 Binary files /dev/null and b/doc/actionDemo/20191210-175409-actionDemo.gif differ diff --git a/src/main/java/cn/edu/scau/biubiusuisui/annotation/FXRedirect.java b/src/main/java/cn/edu/scau/biubiusuisui/annotation/FXRedirect.java new file mode 100644 index 0000000..5bcd08d --- /dev/null +++ b/src/main/java/cn/edu/scau/biubiusuisui/annotation/FXRedirect.java @@ -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; +} diff --git a/src/main/java/cn/edu/scau/biubiusuisui/config/FXPlusApplication.java b/src/main/java/cn/edu/scau/biubiusuisui/config/FXPlusApplication.java index 5402e06..4b396f5 100644 --- a/src/main/java/cn/edu/scau/biubiusuisui/config/FXPlusApplication.java +++ b/src/main/java/cn/edu/scau/biubiusuisui/config/FXPlusApplication.java @@ -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 sets = new HashSet<>(); - for(String dir : dirs){ + for (String dir : dirs) { sets.add(dir); } Set classNames = new HashSet<>(); - for(String dir:sets){ + for (String dir : sets) { ClassUtils classUtils = new ClassUtils(); List 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); } } } diff --git a/src/main/java/cn/edu/scau/biubiusuisui/entity/FXBaseController.java b/src/main/java/cn/edu/scau/biubiusuisui/entity/FXBaseController.java index 1ac6ed8..21803a1 100644 --- a/src/main/java/cn/edu/scau/biubiusuisui/entity/FXBaseController.java +++ b/src/main/java/cn/edu/scau/biubiusuisui/entity/FXBaseController.java @@ -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 instance - * + * 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 instance */ -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() { diff --git a/src/main/java/cn/edu/scau/biubiusuisui/entity/FXFieldWarpper.java b/src/main/java/cn/edu/scau/biubiusuisui/entity/FXFieldWrapper.java similarity index 88% rename from src/main/java/cn/edu/scau/biubiusuisui/entity/FXFieldWarpper.java rename to src/main/java/cn/edu/scau/biubiusuisui/entity/FXFieldWrapper.java index 707072e..c9dbe16 100644 --- a/src/main/java/cn/edu/scau/biubiusuisui/entity/FXFieldWarpper.java +++ b/src/main/java/cn/edu/scau/biubiusuisui/entity/FXFieldWrapper.java @@ -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; diff --git a/src/main/java/cn/edu/scau/biubiusuisui/entity/FXPlusContext.java b/src/main/java/cn/edu/scau/biubiusuisui/entity/FXPlusContext.java index c0ae09e..dd3959b 100644 --- a/src/main/java/cn/edu/scau/biubiusuisui/entity/FXPlusContext.java +++ b/src/main/java/cn/edu/scau/biubiusuisui/entity/FXPlusContext.java @@ -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); } - } diff --git a/src/main/java/cn/edu/scau/biubiusuisui/example/actionDemo/Demo.java b/src/main/java/cn/edu/scau/biubiusuisui/example/actionDemo/Demo.java index 2d10005..974384d 100644 --- a/src/main/java/cn/edu/scau/biubiusuisui/example/actionDemo/Demo.java +++ b/src/main/java/cn/edu/scau/biubiusuisui/example/actionDemo/Demo.java @@ -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; diff --git a/src/main/java/cn/edu/scau/biubiusuisui/example/actionDemo/MainController.java b/src/main/java/cn/edu/scau/biubiusuisui/example/actionDemo/MainController.java index 3a50995..0cfc239 100644 --- a/src/main/java/cn/edu/scau/biubiusuisui/example/actionDemo/MainController.java +++ b/src/main/java/cn/edu/scau/biubiusuisui/example/actionDemo/MainController.java @@ -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() { + @Override + public void changed(ObservableValue observable, String oldValue, String newValue) { + if (null == newValue || "".equals(newValue)) { + time.setText("0"); + } else if (!newValue.matches("^[0-9]*$")) { + time.setText(oldValue); + } + } + }); + } } diff --git a/src/main/java/cn/edu/scau/biubiusuisui/example/listDemo/MainController.java b/src/main/java/cn/edu/scau/biubiusuisui/example/listDemo/MainController.java index ec94845..a5188de 100644 --- a/src/main/java/cn/edu/scau/biubiusuisui/example/listDemo/MainController.java +++ b/src/main/java/cn/edu/scau/biubiusuisui/example/listDemo/MainController.java @@ -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 list; + private ListView userNameListView; - public ObservableList hello(){ - return FXCollections.observableList(new ArrayList(){{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); } } diff --git a/src/main/java/cn/edu/scau/biubiusuisui/example/listDemo/User.java b/src/main/java/cn/edu/scau/biubiusuisui/example/listDemo/User.java index 7b224b8..3b9820a 100644 --- a/src/main/java/cn/edu/scau/biubiusuisui/example/listDemo/User.java +++ b/src/main/java/cn/edu/scau/biubiusuisui/example/listDemo/User.java @@ -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 names = new ArrayList<>(); + + public User() { +// names.add("hello "); +// names.add("test"); + } + + + public void addNames(String name) { + names.add(name); + } + public String getName() { return name; } diff --git a/src/main/java/cn/edu/scau/biubiusuisui/example/mqDemo/MQDemo.java b/src/main/java/cn/edu/scau/biubiusuisui/example/mqDemo/MQDemo.java new file mode 100644 index 0000000..3b02c2f --- /dev/null +++ b/src/main/java/cn/edu/scau/biubiusuisui/example/mqDemo/MQDemo.java @@ -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); + } +} diff --git a/src/main/java/cn/edu/scau/biubiusuisui/example/mqDemo/MainController.java b/src/main/java/cn/edu/scau/biubiusuisui/example/mqDemo/MainController.java new file mode 100644 index 0000000..daea5f1 --- /dev/null +++ b/src/main/java/cn/edu/scau/biubiusuisui/example/mqDemo/MainController.java @@ -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"); + } + +} diff --git a/src/main/java/cn/edu/scau/biubiusuisui/example/mqDemo/TopBarController.java b/src/main/java/cn/edu/scau/biubiusuisui/example/mqDemo/TopBarController.java new file mode 100644 index 0000000..1338992 --- /dev/null +++ b/src/main/java/cn/edu/scau/biubiusuisui/example/mqDemo/TopBarController.java @@ -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; + } +} diff --git a/src/main/java/cn/edu/scau/biubiusuisui/example/redirectDemo/DialogController.java b/src/main/java/cn/edu/scau/biubiusuisui/example/redirectDemo/DialogController.java new file mode 100644 index 0000000..62ebcf5 --- /dev/null +++ b/src/main/java/cn/edu/scau/biubiusuisui/example/redirectDemo/DialogController.java @@ -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 { +} diff --git a/src/main/java/cn/edu/scau/biubiusuisui/example/redirectDemo/LoginController.java b/src/main/java/cn/edu/scau/biubiusuisui/example/redirectDemo/LoginController.java new file mode 100644 index 0000000..bded7c2 --- /dev/null +++ b/src/main/java/cn/edu/scau/biubiusuisui/example/redirectDemo/LoginController.java @@ -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"; + } +} diff --git a/src/main/java/cn/edu/scau/biubiusuisui/example/redirectDemo/RedirectDemo.java b/src/main/java/cn/edu/scau/biubiusuisui/example/redirectDemo/RedirectDemo.java new file mode 100644 index 0000000..26e071c --- /dev/null +++ b/src/main/java/cn/edu/scau/biubiusuisui/example/redirectDemo/RedirectDemo.java @@ -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); + } +} diff --git a/src/main/java/cn/edu/scau/biubiusuisui/example/redirectDemo/RegisterController.java b/src/main/java/cn/edu/scau/biubiusuisui/example/redirectDemo/RegisterController.java new file mode 100644 index 0000000..b945759 --- /dev/null +++ b/src/main/java/cn/edu/scau/biubiusuisui/example/redirectDemo/RegisterController.java @@ -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"; + } +} + diff --git a/src/main/java/cn/edu/scau/biubiusuisui/example/redirectDemo/SuccessController.java b/src/main/java/cn/edu/scau/biubiusuisui/example/redirectDemo/SuccessController.java new file mode 100644 index 0000000..d356c8c --- /dev/null +++ b/src/main/java/cn/edu/scau/biubiusuisui/example/redirectDemo/SuccessController.java @@ -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) { + + } + +} diff --git a/src/main/java/cn/edu/scau/biubiusuisui/factory/FXControllerFactory.java b/src/main/java/cn/edu/scau/biubiusuisui/factory/FXControllerFactory.java index ba12fab..68908a7 100644 --- a/src/main/java/cn/edu/scau/biubiusuisui/factory/FXControllerFactory.java +++ b/src/main/java/cn/edu/scau/biubiusuisui/factory/FXControllerFactory.java @@ -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; } } diff --git a/src/main/java/cn/edu/scau/biubiusuisui/factory/FXEntityFactory.java b/src/main/java/cn/edu/scau/biubiusuisui/factory/FXEntityFactory.java index e2438c2..7a1b337 100644 --- a/src/main/java/cn/edu/scau/biubiusuisui/factory/FXEntityFactory.java +++ b/src/main/java/cn/edu/scau/biubiusuisui/factory/FXEntityFactory.java @@ -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 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 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; } - } diff --git a/src/main/java/cn/edu/scau/biubiusuisui/function/FXWindowParser.java b/src/main/java/cn/edu/scau/biubiusuisui/function/FXWindowParser.java index dc548bd..95142dd 100644 --- a/src/main/java/cn/edu/scau/biubiusuisui/function/FXWindowParser.java +++ b/src/main/java/cn/edu/scau/biubiusuisui/function/FXWindowParser.java @@ -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); diff --git a/src/main/java/cn/edu/scau/biubiusuisui/messageQueue/MessageQueue.java b/src/main/java/cn/edu/scau/biubiusuisui/messageQueue/MessageQueue.java index 0bade96..29c164e 100644 --- a/src/main/java/cn/edu/scau/biubiusuisui/messageQueue/MessageQueue.java +++ b/src/main/java/cn/edu/scau/biubiusuisui/messageQueue/MessageQueue.java @@ -19,31 +19,32 @@ import java.util.concurrent.ConcurrentHashMap; public class MessageQueue { - - private static Map> receivers = new ConcurrentHashMap<>(); + private static Map> 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 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 lists = receivers.get(id); if (lists != null) { for (FXMethodEntity fxMethodEntity : lists) { diff --git a/src/main/java/cn/edu/scau/biubiusuisui/proxy/FXControllerProxy.java b/src/main/java/cn/edu/scau/biubiusuisui/proxy/FXControllerProxy.java index ad7df9d..c07303d 100644 --- a/src/main/java/cn/edu/scau/biubiusuisui/proxy/FXControllerProxy.java +++ b/src/main/java/cn/edu/scau/biubiusuisui/proxy/FXControllerProxy.java @@ -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) { diff --git a/src/main/java/cn/edu/scau/biubiusuisui/proxy/FXEntityProxy.java b/src/main/java/cn/edu/scau/biubiusuisui/proxy/FXEntityProxy.java index 339c979..4fc6106 100644 --- a/src/main/java/cn/edu/scau/biubiusuisui/proxy/FXEntityProxy.java +++ b/src/main/java/cn/edu/scau/biubiusuisui/proxy/FXEntityProxy.java @@ -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 fxFieldWarpperMap; + private Map 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 getFxFieldWarpperMap() { - return fxFieldWarpperMap; + public Map getFxFieldWrapperMap() { + return fxFieldWrapperMap; } - public void setFxFieldWarpperMap(Map fxFieldWarpperMap) { - this.fxFieldWarpperMap = fxFieldWarpperMap; + public void setFxFieldWrapperMap(Map fxFieldWrapperMap) { + this.fxFieldWrapperMap = fxFieldWrapperMap; } } diff --git a/src/main/java/cn/edu/scau/biubiusuisui/stage/StageManager.java b/src/main/java/cn/edu/scau/biubiusuisui/stage/StageManager.java new file mode 100644 index 0000000..910e871 --- /dev/null +++ b/src/main/java/cn/edu/scau/biubiusuisui/stage/StageManager.java @@ -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 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(); + } +} diff --git a/src/main/java/cn/edu/scau/biubiusuisui/utils/BeanUtil.java b/src/main/java/cn/edu/scau/biubiusuisui/utils/BeanUtil.java index 54ed9aa..f4755e1 100644 --- a/src/main/java/cn/edu/scau/biubiusuisui/utils/BeanUtil.java +++ b/src/main/java/cn/edu/scau/biubiusuisui/utils/BeanUtil.java @@ -14,6 +14,6 @@ public class BeanUtil { if(fxEntityProxy == null){ return null; } - return fxEntityProxy.getFxFieldWarpperMap().get(fieldName).getProperty(); + return fxEntityProxy.getFxFieldWrapperMap().get(fieldName).getProperty(); } } diff --git a/src/main/java/cn/edu/scau/biubiusuisui/utils/ClassUtils.java b/src/main/java/cn/edu/scau/biubiusuisui/utils/ClassUtils.java index 3bbbda8..f30884a 100644 --- a/src/main/java/cn/edu/scau/biubiusuisui/utils/ClassUtils.java +++ b/src/main/java/cn/edu/scau/biubiusuisui/utils/ClassUtils.java @@ -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 getAllFXControllerClassName(String base, List nameList) { String splashPath = StringUtils.dotToSplash(base); - URL url = cl.getResource(splashPath); + URL url = classLoader.getResource(splashPath); String filePath = StringUtils.getRootPath(url); List 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 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()); diff --git a/src/main/java/cn/edu/scau/biubiusuisui/utils/StringUtils.java b/src/main/java/cn/edu/scau/biubiusuisui/utils/StringUtils.java index c5279e3..d1b9e32 100644 --- a/src/main/java/cn/edu/scau/biubiusuisui/utils/StringUtils.java +++ b/src/main/java/cn/edu/scau/biubiusuisui/utils/StringUtils.java @@ -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; } diff --git a/src/main/resources/actionDemo.fxml b/src/main/resources/actionDemo.fxml deleted file mode 100644 index 8c0c289..0000000 --- a/src/main/resources/actionDemo.fxml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - diff --git a/src/main/resources/actionDemo/actionDemo.fxml b/src/main/resources/actionDemo/actionDemo.fxml new file mode 100644 index 0000000..b7ddf40 --- /dev/null +++ b/src/main/resources/actionDemo/actionDemo.fxml @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/src/main/resources/listDemo.fxml b/src/main/resources/listDemo/listDemo.fxml similarity index 59% rename from src/main/resources/listDemo.fxml rename to src/main/resources/listDemo/listDemo.fxml index ea36b91..92d54be 100644 --- a/src/main/resources/listDemo.fxml +++ b/src/main/resources/listDemo/listDemo.fxml @@ -3,10 +3,9 @@ - - - -