31 Commits
v1.0 ... v1.1.1

Author SHA1 Message Date
suisui
9a542c6caa 修正部分api名称不一致的问题,新增firstDemo示例代码,展现精细化操作时该如何编写代码 2020-01-01 23:45:25 +08:00
suisui
1eb81ed37e 删除out和.idea 2019-12-10 23:59:31 +08:00
suisui
3c3c556a19 调整文件结构 2019-12-10 23:58:20 +08:00
suisui
6d5f97767d 解决README中gif无法正常显示的问题:上传gif 2019-12-10 23:29:38 +08:00
suisui
8c264a6100 解决README中gif无法正常显示的问题 2019-12-10 23:21:24 +08:00
suisui
c0684c7501 1. 新增了多窗口切换功能
2. 新增多个example示例可供使用参考
3. 修正信号收发机制的bug
4. 规范化部分代码,并加以部分注释
5. 修改README
2019-12-10 23:04:44 +08:00
Biubiu
5cc7e57a88 add LICENSE. 2019-12-02 20:53:44 +08:00
Biubiu
2596af27ed 修改README 2019-11-25 21:06:11 +08:00
Biubiu
4c1cc13601 更新 README.md 2019-07-30 09:33:39 +08:00
billkiller
f731b73207 修复了bug,调整了框架中类和函数命名 2019-07-28 02:00:14 +08:00
billkiller
c74ea3039f Merge branch 'master' of https://gitee.com/Biubiuyuyu/JavaFX-Plus 2019-07-27 22:40:43 +08:00
billkiller
bc421b87b9 支持函数表达式和change表达式 2019-07-27 22:37:52 +08:00
Biubiu
dcf02d6565 更新 README.md 2019-07-26 11:43:41 +08:00
Biubiu
986f43ad6d 更新 README.md 2019-07-25 15:10:36 +08:00
Biubiu
cacb8b154b 更新 README.md 2019-07-25 15:07:02 +08:00
billkiller
7b5e56d6f7 Merge branch 'master' of https://gitee.com/Biubiuyuyu/JavaFX-Plus 2019-07-25 10:05:08 +08:00
billkiller
48889c54a9 解决了基本类型错误bug 2019-07-25 10:04:34 +08:00
Biubiu
f715cced3d 更新 README.md 2019-07-24 23:22:45 +08:00
Biubiu
fcf17ac57f 更新 README.md 2019-07-24 23:17:13 +08:00
billkiller
34ae7db92f 解决spring的Bug以及实现了EL表达式绑定基本元素属性 2019-07-24 23:00:38 +08:00
billkiller
6fcd94e94b Merge branch 'master' of https://gitee.com/Biubiuyuyu/JavaFX-Plus 2019-07-07 12:23:02 +08:00
billkiller
7ce75c9206 实现FX-PLus和Spring结合的Demo 2019-07-07 12:21:30 +08:00
Biubiu
deb5e7f3e8 更新 README.md 2019-07-05 15:56:35 +08:00
billkiller
bb53425b43 修复了文件丢失问题 2019-07-04 11:09:05 +08:00
billkiller
573f3e1c70 Merge branch 'master' of https://gitee.com/Biubiuyuyu/JavaFX-Plus 2019-07-04 11:02:14 +08:00
billkiller
40b81fa8d8 修复了文件丢失问题 2019-07-04 11:01:27 +08:00
billkiller
5cd92e9e8f 修复了文件丢失问题 2019-07-04 10:59:17 +08:00
Biubiu
efd34fb512 更新 README.md 2019-06-30 13:56:45 +08:00
billkiller
059c5c8193 快速配置可拖动窗口,无标题窗口 2019-06-30 13:44:35 +08:00
Biubiu
953c6b16ad 更新 README.md 2019-06-29 16:18:20 +08:00
Biubiu
a50ec834d1 更新 README.md 2019-06-29 16:17:36 +08:00
165 changed files with 3452 additions and 2567 deletions

View File

@@ -1,12 +0,0 @@
<component name="ArtifactManager">
<artifact type="jar" name="JavaFx-Plus:jar">
<output-path>$PROJECT_DIR$/out/artifacts/JavaFx_Plus_jar</output-path>
<root id="archive" name="JavaFx-Plus.jar">
<element id="module-output" name="JavaFx-Plus" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/cglib/cglib/3.1/cglib-3.1.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/ow2/asm/asm/4.2/asm-4.2.jar" path-in-jar="/" />
<element id="library" level="project" name="Maven: cglib:cglib:3.1" />
<element id="library" level="project" name="Maven: org.ow2.asm:asm:4.2" />
</root>
</artifact>
</component>

16
.idea/compiler.xml generated
View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="JavaFx-Plus" />
</profile>
</annotationProcessing>
<bytecodeTargetLevel>
<module name="JavaFx-Plus" target="1.8" />
</bytecodeTargetLevel>
</component>
</project>

View File

@@ -1,13 +0,0 @@
<component name="libraryTable">
<library name="Maven: cglib:cglib:3.1">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/cglib/cglib/3.1/cglib-3.1.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/cglib/cglib/3.1/cglib-3.1-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/cglib/cglib/3.1/cglib-3.1-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -1,13 +0,0 @@
<component name="libraryTable">
<library name="Maven: junit:junit:4.11">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/junit/junit/4.11/junit-4.11.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/junit/junit/4.11/junit-4.11-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/junit/junit/4.11/junit-4.11-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -1,13 +0,0 @@
<component name="libraryTable">
<library name="Maven: org.hamcrest:hamcrest-core:1.3">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -1,13 +0,0 @@
<component name="libraryTable">
<library name="Maven: org.ow2.asm:asm:4.2">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/ow2/asm/asm/4.2/asm-4.2.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/ow2/asm/asm/4.2/asm-4.2-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/ow2/asm/asm/4.2/asm-4.2-sources.jar!/" />
</SOURCES>
</library>
</component>

13
.idea/misc.xml generated
View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

8
.idea/modules.xml generated
View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/JavaFx-Plus.iml" filepath="$PROJECT_DIR$/JavaFx-Plus.iml" />
</modules>
</component>
</project>

124
.idea/uiDesigner.xml generated
View File

@@ -1,124 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

1409
.idea/workspace.xml generated
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="Spring" name="Spring">
<configuration />
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Biubiu
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

599
README.md
View File

@@ -1,81 +1,75 @@
# JavaFX-Plus
- [JavaFX-Plus](#javafx-plus)
* [前言](#前言)
+ [开发进程](#开发进程)
* [Maven仓库地址](#Maven仓库地址)
* [框架功能描述](#框架功能描述)
+ [模块化开发](#模块化开发)
- [介绍](#介绍)
- [如何创建模块](#如何创建模块)
- [scenebuilder中导入刚刚生成的上面的控件](#scenebuilder中导入刚刚生成的上面的控件)
+ [与Spring的融合](#与Spring的融合)
+ [信号机制](#信号机制)
+ [JavaBean与JavaFXBean的转换](#JavaBean与JavaFXBean的转换)
+ [可拔插功能](#可拔插功能)
+ [数据绑定](#数据绑定)
- [Bean和View绑定](#Bean和View绑定)
- [View和View绑定](#View和View绑定)
- [函数表达式绑定](#函数表达式绑定)
+ [多窗口切换功能](#多窗口切换功能)
* [框架的使用](#框架的使用)
+ [内置注解](#内置注解)
+ [两个工厂和一个context](#两个工厂和一个context)
* [创建第一个程序](#创建第一个程序)
**1.1 前言**
**1.1.1 为什么要出这个框架**
## 前言
![输入图片说明](https://images.gitee.com/uploads/images/2019/0629/155142_1235eb9c_2067650.png "JavaFX-Plus.png")
这个框架不是UI美化框架为了简化javaFX项目开发、为了减少项目之间组件耦合而打造的框架。目前框架主要功能如下图所示
记得从刚开始学习Java就开始接触JavaFX从一开始的代码编写图形到后来通过FXML编写界面一步步的学习之中逐渐领悟JavaFX的强大与灵活我对JavaFX这门生不逢时的技术有了独特的感情可以说JavaFX的强大不被许多人了解。
![JavaFx-Plus](doc/JavaFX-Plus.png)
### 开发进程
2019年11月25日起项目暂停更新将会下次发布将会升级为2.0版本,到时候将会提供更多数据绑定操作,以及优化性能。
随着不断深入我也渐渐发现JavaFx的设计思想在很多时候是无法满足当代程序开发思想的并且一些功能并不是特别容易被使用所以特定开发了一套简化开发JavaFx开发过程的框架供大家使用希望能够简化大家的操作将精力专注于主要业务。
- [x] 模块化
- [x] 与Spring的融合
- [x] 信号机制
- [x] JavaBean和JavaFXBean的转换
- [x] 可拔插功能(窗口拖动等功能)
- [x] 数据绑定
- [x] Bean和View的绑定
- [x] View和View的绑定
- [x] 函数表达式绑定
- [x] 多窗口切换功能
- [ ] 事件注解绑定
- [ ] 数据校验
- [ ] 键盘事件绑定
- [ ] 优化性能
下面是我在开发过程中遇到的一些问题,我也针对这些问题做了简化操作。
## Maven仓库地址
```xml
**1.1.2 FX缺点1 : 单一控制器臃肿**
<dependency>
<groupId>com.gitee.Biubiuyuyu</groupId>
<artifactId>javafx-plus</artifactId>
<version>1.0.0-RELEASE</version>
</dependency>
JavaFX中似乎都是一个Controller把所有的操作和控件囊括在里面一个Controller有几百行甚至几千行程序虽然不用考虑模块之间调用问题了但是这几千行的代码却很难被管理。
![输入图片说明](https://images.gitee.com/uploads/images/2019/0629/021926_d36374fc_2067650.png "bigController.png")
图1 臃肿的controller
**1.1.3 FX缺点2 : 控制类控制能力弱**
JavaFX启动的Stage和Controller之间总是隔着远远的距离并且由于Controller是由JavaFX注入生成的所以很多非Controller的东西与Controller交流导致了不得不得使用静态方法或者静态成员这类小技巧来实现交流导致代码变"丑"
**1.1.4 FX缺点3 : JavaBean无法使用Property**
JavaFX的设计哲学是所有的JavaBean的属性都是property类型的可是很多时候我们的JavaBean都是StringInteger这类基本类型要重新修改类属性所带来的问题就足以让人让而却步了。
```java
//普通JavaBean对象
public class Student {
private String name;
private int age;
private String gender;
private String code;
}
```
## 框架功能描述
```java
//简单的JavaFX bean对象
class Bill {
// 定义一个变量存储属性
private DoubleProperty amountDue = new SimpleDoubleProperty();
### 模块化开发
// 定义一个getter方法获取属性值
public final double getAmountDue(){return amountDue.get();}
#### 介绍
// 定义一个setter方法设置属性值
public final void setAmountDue(double value){amountDue.set(value);}
在Java开发过程中很多界面是相似或者重复的如果能够将这些界面打包成为一个自定义控件并且通过Scenebuilder拖动就能产生一个控件那将会大大提高我们的开发效率。所以我们提出将不同区域划分为不同的子模块已达到减少耦合和加速并行开发。一般我们经常把界面分为顶部工具栏左边导航栏右侧的内容栏如果全部内容都写在一个Controller那么将会导致十分臃肿我们希望将不同的区域划分开来分而治之。
// 定义一个getter方法获取属性本身
public DoubleProperty amountDueProperty() {return amountDue;}
#### 如何创建模块
}
```
**1.1.5 总结**
为了解决上述问题我开发了一套增强JavaFX功能的框架来起到简化JavaFX开发过程的问题。
**1.2 特色一:模块化开发**
1.2.1 介绍
在Java开发过程中很多界面是相似或者重复的如果能够将这些界面打包成为一个自定义控件并且通过Scenebuilder拖动就能产生一个控件那将会大大提高我们的开发效率。所以我们提出将不同区域划分为不同的子模块已达到减少耦合和加速并行开发。一般我们经常把界面分为顶部工具栏左边导航栏右侧的内容栏如果全部内容都写在一个Controller那么将会导致十分臃肿我们希望将不同的区域划分开来分而治之。
1.2.2 如何创建模块
只要新建一个类继承自FXBaseController而FXBaseController是继承于Pane这就是JavaFX-Plus的设计思想之一切皆为Pane。在类上标上FXController注解提供FXML文件的地址。如果设置为FXWindow那么将会把这个Controller以单独的Window显示这里仅仅几句代码就实现了一个简单的窗口程序。
只要新建一个类继承自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")
@@ -85,56 +79,112 @@ class Bill {
图3 显示结果
1.2.3 scenebuilder中导入刚刚生成的上面的控件
#### scenebuilder中导入刚刚生成的上面的控件
![输入图片说明](https://images.gitee.com/uploads/images/2019/0629/022036_e128f313_2067650.gif "modulesAction.gif")
图4 模块化操作
**1.3 特色2 :信号机制**
有两个主要标签一个是FXSender这个标签作用在方法上标记这个方法为信号发射方法。可以通过设置name修改这个信号发射方法的名称默认是函数名字。
发射信号会被订阅这个发射函数的所有FXReceiver接收并且发射函数的返回值会作为参数传进这个函数之中。而且这种发送和接受关系是全局的只要是注册了的Controller都可以进行接受不局限于同一个Controller。
### 与Spring的融合
我们通过一个简单的代码来理解一下
可以快速支持Spring和这个框架的融合只需要一行代码就可将实例的生成控制转交给容器管理
代码如下:
```java
@FXController(path = "Main.fxml")
@FXWindow(title = "demo1")
public class MainController extends FXBaseController{
@FXML
Button btn;
@FXML
Label label;
/**
鼠标之后,系统通过会发射信号,调用所有订阅这个发射信号函数的方法响应信号
*/
@FXML //绑定鼠标点击事件
@FXSender //标注为信号发射函数
public String send(){
System.out.println("before sending"); //输出 before sending
return "sending msg";
@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属性的创建
}
});
}
/**
接受者必须指定要订阅的发送者类名+方法名
而且发送函数的返回值会注入到接受函数的参数中
*/
@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")
**1.4 特色3 :JavaBean 和 JavaFxBean**
一般我们写的JavaBean都是基本类型的但是JavaFXBean的设计哲学是这些属性都应该是JavaFX定义的Property类型这十分不利于我们的开发我们如何在不修改JavaBean的条件下使用到JavaFX的Property的一些优良方法呢答案是我们通过反射获得基本类型对应的Property目前仅限于booleandoubleintegerlongstringfloat等基本类型不支持List等封装对象。
### 信号机制
有两个主要标签一个是FXSender这个标签作用在函数上标记这个方法为信号发射函数。可以通过设置name修改这个信号发射函数的名称默认是函数名字。
发射信号会被订阅了这个发射函数的所有FXReceiver接收并且发射函数的返回值会作为参数传进这个函数之中。而且这种发送和接收关系是全局的只要是注册了的Controller都可以进行接收不局限于同一个Controller。
我们通过一个简单的代码来理解一下主要实现自定义组件导航栏TopBar主界面中包含该组件当用户点击导航栏某些按钮时能返回主界面相关信息。fxml文件详见resources下的mqDemo文件夹。
1. 利用JavaFX的模块化我们设计一个简单的导航栏
```java
@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;
}
}
```
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");
}
}
```
![20191208-194336-signalshow](doc/mqDemo/20191208-194336-signalshow.gif)
### JavaBean与JavaFXBean的转换
一般我们写的JavaBean都是基本类型的但是JavaFXBean的设计哲学是这些属性都应该是JavaFX定义的Property类型这十分不利于我们的开发我们如何在不修改JavaBean的条件下使用到JavaFX的Property的一些优良方法呢答案是我们通过反射获得基本类型对应的Property目前仅限于booleandoubleintegerlongstringfloatList等基本类型不支持封装对象。
![输入图片说明](https://images.gitee.com/uploads/images/2019/0629/095306_9950a9af_2067650.png "微信截图_20190629095237.png")
@@ -242,37 +292,338 @@ public class Student {
直接操作JavaBean类就会通过动态绑定修改界面不需要讲JavaBean转换为JavaFX Bean可以减少开发中的类型转换。
### 可拔插功能
在本框架中实现了窗口可拖动和窗口可伸缩在Javafx中如果一个窗口隐藏了标题栏那么这个窗口也就没办法拖动和伸缩了在JavaFX-Plus中你就不需有这种烦恼只需要在@FXWindow中设置
```java
@FXWindow(title = "demo1",dragable = true,style = StageStyle.UNDECORATED)
```
就可以让这个没有标题的窗口可以被拖动而且能拉伸(默认打开,可以关闭)
![输入图片说明](https://images.gitee.com/uploads/images/2019/0630/135524_d0b03d5f_2067650.gif "moveable.gif")
**2 如何使用这个框架**
![输入图片说明](https://images.gitee.com/uploads/images/2019/0630/135637_cb0e0a89_2067650.gif "resizeAble.gif")
2.1 了解内置注解
### 数据绑定
| 名字 | 作用 | 参数 | 要求 |
| ------------- | ------------------------------------------------------------ | --------------------------------------- | -------------------- |
| @FXScan | 扫描@FXEntity和@FXController注解标记的类 | 要扫描的目录 | 默认当前目录之下所有 |
| @FXController | 标记这个类为控件 | fxml文件地址 | 无 |
| @FXWindow | 标记这个控件要以单独窗口显示 | title是窗口名字也可以设置窗口长度宽度 | 无 |
| @FXEntity | 标记JavaBean系统会自动识别@FXField然后包装JavaBean为JavaFXBean | 重命名 | |
| @FXField | 代表这个属性要映射为Property属性 | | |
| @FXSender | 信号发送者 | name可以重命名信号 | |
| @FXReceiver | 信号接收函数 | name是订阅的发射者函数名 | 不可空 |
与之相关的注解有`@FXBind`注解在JavaFX控件的字段上面标明该变量的绑定方式和绑定属性类似于Vue中的界面绑定。目前已实现Bean和View的绑定、View和View的绑定、函数表达式的绑定
2.2 两个工厂和一个context
#### Bean和View绑定
如下面代码通过FXBind将Student的姓名与文本框输入内容绑定学生的密码和密码框输入框内容绑定完全简化了数据传递操作代码中完全没有出现界面数据传输到控制器代码。
例子:
```java
@FXData
@FXBind(
{
"name=${usr.text}",
"password=${psw.text}"
}
)
Student student = new Student();
@FXML
private PasswordField psw;
@FXML
private Label pswMsg;
@FXML
void login(ActionEvent event) {
System.out.println("user:" + student.getName());
System.out.println("psw:" + student.getPassword());
if ("admin".equals(student.getName()) && "admin".equals(student.getPassword())) {
System.out.println("Ok");
} else {
System.out.println("fail");
}
}
```
如图所示:
![输入图片说明](https://images.gitee.com/uploads/images/2019/0724/231705_976181ba_2067650.gif "expression.gif")
#### View和View绑定
```java
@FXBind("text=${psw.text}")
@FXML
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)
### 多窗口切换功能
#### 介绍
在JavaFX中常常需要多个窗口之间进行切换比如登录窗口点击登录后跳转至登录成功/失败窗口网上部分有关多窗口切换的JavaFX教程实现过程为在Controller中是实现FXML绑定并通过外部调用某个show方法来切换窗口。由于本框架已经将FXML绑定这一功能封装故通过在Controller内部直接初始化Stage并设置参数这一方法并不现实。因此在本框架中编写StageController类对Controller进行管理。
#### 涉及到的注解
`@FXController`标记于类上用于绑定FXML文件需要注意的是标记了`FXController`只能标记这是一个控件。
`@FXWindow`标记于类上标记这个Controller需要以窗口显示只有需要以单独窗口显示时才会被重定向。
`@FXRedirect`:标记于函数上,标记该函数用于处理重定向。
#### 规定
本框架规定,当需要使用`@FXRedirect`标记函数处理重定向时函数必须是返回String类型的函数且返回已注册的Controller名如需要重定向至登录成功界面控制器为`SuccessController`,则需要写上`return "SuccessController"。
#### 使用方法
1. `FXRedirect`注解的使用如下:
```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. 跳转至另一个窗口(关闭原窗口)
![20191208-125739-close](doc/redirectDemo/20191208-125739-close.gif)
2. 弹窗形式弹出窗口(不关闭原窗口)
![20191208-125511-not close](doc/redirectDemo/20191208-125511-not_close.gif)
#### 不足之处
暂未实现携带数据的窗口跳转目前只实现纯粹跳转到另一个Controller。
## 框架的使用
### 内置注解
| 名字 | 作用 | 参数 | 要求 |
| ------------- | ------------------------------------------------------------ | --------------------------------------- | ---------------------------------------- |
| @FXData | 标明这个普通bean要装配成javafxBean | fx_id | 重新命名 |
| @FXScan | 扫描@FXEntity和@FXController注解标记的类 | 要扫描的目录 | 默认当前目录之下所有 |
| @FXController | 标记这个类为控件 | pathfxml文件地址 | 无 |
| @FXWindow | 标记这个控件要以单独窗口显示 | title是窗口名字也可以设置窗口长度宽度 | 无 |
| @FXEntity | 标记JavaBean系统会自动识别@FXField然后包装JavaBean为JavaFXBean | 重命名 | |
| @FXField | 代表这个属性要映射为Property属性 | | |
| @FXSender | 信号发送者 | name重命名信号 | |
| @FXReceiver | 信号接收函数 | name订阅的发射者函数名 | 不可空 |
| @FXRedirect | 标记函数为重定向函数 | close是否关闭当前窗口 | 返回值为某个使用了FXView注解的Controller |
### 两个工厂和一个context
1. 两个工厂
在JavaFX-Plus中所有Controller对象和FXEnity对象都必须通过工厂创建。
```
student = (Student) FXEntityFactory.getInstance().createJavaBeanProxy(Student.class); //工厂产生一个学生
```java
student = (Student) FXEntityFactory.getInstance().wrapFxBean(Student.class); //工厂产生一个学生
```
通过工厂创建JavaBean在创建同时工厂会对JavaBean代理并且包装对应的Property属性。
通过工厂创建JavaBean在创建同时工厂会对JavaBean代理并且包装对应的Property属性。
```
```java
MainController mainController = (MainController)FXFactory.getFXController(MainController.class);
```
2.3 第一个Demo如何使用框架创建第一个程序
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的类进行初始化
@@ -282,26 +633,21 @@ public class Demo extends Application {
FXPlusApplication.start(Demo.class); //其他配置和JavaFX相同这里要调用FXPlusAppcalition的start方法开始FX-plus加强
}
}
```
接下来我们生成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;
@@ -319,9 +665,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.wrapFxBean(Student.class); // 从工厂中拿到将JavaBean转换得到的JavaFXBean
Property listProperty = FXPlusContext.getEntityPropertyByName(student, "list");
list.itemsProperty().bind(listProperty);
}
}
@@ -329,11 +675,10 @@ public class MainController extends FXBaseController{
Studen类的定义如下
```java
@FXEntity
public class Student {
@FXField
@FXField //标记该属性是否被生成对应的Property
private String name;
@FXField
@@ -348,6 +693,8 @@ public class Student {
}
```
请注意FXML文件的根标签必须为`<fx:root>`。
```xml
<?xml version="1.0" encoding="UTF-8"?>
@@ -362,10 +709,10 @@ public class Student {
<ListView fx:id="list" layoutX="42.0" layoutY="51.0" prefHeight="275.0" prefWidth="334.0" />
</children>
</fx:root>
```
从我们代码可以看出我们很少有操作界面的操作并且我们操作的对象都是基本类型的对象这样的操作十分有利于我们将普通的项目转换为JavaFX项目最终运行起来将会是这样
![输入图片说明](https://images.gitee.com/uploads/images/2019/0629/160249_00f41d22_2067650.gif "helloWorldDemo.gif")

BIN
doc/JavaFX-Plus.png Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 MiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 MiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 MiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 MiB

View File

Binary file not shown.

133
pom.xml
View File

@@ -3,13 +3,33 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<name>javafx-plus</name>
<groupId>com.gitee.Biubiuyuyu</groupId>
<artifactId>javafx-plus</artifactId>
<version>1.0.0-RELEASE</version>
<packaging>jar</packaging>
<groupId>groupId</groupId>
<artifactId>JavaFx-Plus</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.sonatype.oss</groupId>
<artifactId>oss-parent</artifactId>
<version>7</version>
</parent>
<description>this is javafx framework that simplified coding</description>
<distributionManagement>
<repository>
<id>javafx-plus</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
<snapshotRepository>
<id>javafx-plus</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
<dependencies>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
@@ -22,8 +42,6 @@
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
@@ -31,12 +49,113 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgs>
<!-- 过期的方法的警告-->
<arg>-Xlint:deprecation</arg>
</compilerArgs>
<compilerArguments>
<!-- 是否输出所有的编译信息(包括类的加载等)-->
<!--<verbose />-->
<!-- 解决maven命令编译报错因为rt.jar 和jce.jar在jre的lib下面不在jdk的lib下面
导致maven找不到java7以后会出现这个问题将这2个jar包拷贝到jdk的lib下面估计也好使-->
<bootclasspath>${java.home}/lib/rt.jar:${java.home}/lib/jce.jar</bootclasspath>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>release</id>
<build>
<plugins>
<!-- Source -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<additionalparam>-Xdoclint:none</additionalparam>
</configuration>
</execution>
</executions>
</plugin>
<!-- GPG -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<licenses>
<license>
<name>GNU Lesser General Public License Version 3</name>
<url>http://www.gnu.org/licenses/lgpl.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<scm>
<tag>master</tag>
<url>https://gitee.com/Biubiuyuyu/JavaFX-Plus.git</url>
<connection>scm:git:https://gitee.com/Biubiuyuyu/JavaFX-Plus.git</connection>
<developerConnection>scm:git:https://gitee.com/Biubiuyuyu/JavaFX-Plus.git</developerConnection>
</scm>
<developers>
<developer>
<name>Zhu zhanbiao</name>
<email>747441355@qq.com</email>
<organization>cn.edu.scau</organization>
</developer>
<developer>
<name>Yang suiyu</name>
<email>498870048@qq.com</email>
<organization>cn.edu.scau</organization>
</developer>
</developers>
</project>

View File

@@ -0,0 +1,11 @@
package cn.edu.scau.biubiusuisui.annotation;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Inherited
public @interface FXBind {
String [] value();
}

View File

@@ -4,8 +4,8 @@ import java.lang.annotation.*;
/**
* This is use for marking A controller as FX-Plus Controller
* @Author jack
* @Date:2019/6/25 1:34
@Author jack
@Date:2019/6/25 1:34
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)

View File

@@ -0,0 +1,14 @@
package cn.edu.scau.biubiusuisui.annotation;
import java.lang.annotation.*;
/**
* @Author jack
* @Date:2019/6/25 1:36
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Inherited
public @interface FXData {
String fx_id() default "";
}

View File

@@ -1,9 +1,6 @@
package cn.edu.scau.biubiusuisui.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.*;
/**
* @Author jack
@@ -11,5 +8,6 @@ import java.lang.annotation.Target;
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface FXEntity {
}

View File

@@ -13,8 +13,12 @@ import java.lang.annotation.Target;
@Target(ElementType.FIELD)
public @interface FXField {
boolean readOnly() default false;
String setter() default "";
String add() default "";
String delete() default "";
String edit() default "";
}

View File

@@ -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;
}

View File

@@ -0,0 +1,14 @@
package cn.edu.scau.biubiusuisui.annotation;
import java.lang.annotation.*;
/**
* @Author jack
* @Date:2019/7/27 3:06
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
@Inherited
public @interface FXValue {
String value();
}

View File

@@ -1,9 +0,0 @@
package cn.edu.scau.biubiusuisui.annotation;
/**
* @Author jack
* @Date:2019/6/25 1:36
*/
public @interface FXView {
}

View File

@@ -1,5 +1,7 @@
package cn.edu.scau.biubiusuisui.annotation;
import javafx.stage.StageStyle;
import java.lang.annotation.*;
/**
@@ -12,5 +14,11 @@ import java.lang.annotation.*;
public @interface FXWindow {
double preWidth() default 0.0;
double preHeight()default 0.0;
double minWidth() default 0.0;
double minHeight() default 0.0;
boolean resizable() default false;
boolean draggable() default false;
boolean mainStage() default false;
StageStyle style() default StageStyle.DECORATED;
String title () ;
}

View File

@@ -1,6 +1,56 @@
package cn.edu.scau.biubiusuisui.config;
import javafx.fxml.*;
import cn.edu.scau.biubiusuisui.entity.FXBaseController;
import cn.edu.scau.biubiusuisui.expression.data.MyBeanAdapter;
import cn.edu.scau.biubiusuisui.expression.data.MyExpressionValue;
import cn.edu.scau.biubiusuisui.factory.FXControllerFactory;
import com.sun.javafx.beans.IDProperty;
import com.sun.javafx.fxml.BeanAdapter;
import com.sun.javafx.fxml.LoadListener;
import com.sun.javafx.fxml.ParseTraceElement;
import com.sun.javafx.fxml.PropertyNotFoundException;
import com.sun.javafx.fxml.expression.Expression;
import com.sun.javafx.fxml.expression.KeyPath;
import com.sun.javafx.util.Logging;
import javafx.beans.DefaultProperty;
import javafx.beans.InvalidationListener;
import javafx.beans.property.Property;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.*;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.fxml.JavaFXBuilderFactory;
import javafx.fxml.LoadException;
import javafx.util.Builder;
import javafx.util.BuilderFactory;
import javafx.util.Callback;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.reflect.misc.ConstructorUtil;
import sun.reflect.misc.MethodUtil;
import sun.reflect.misc.ReflectUtil;
import javax.script.*;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.util.StreamReaderDelegate;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.security.AccessController;
import java.security.AllPermission;
import java.security.PrivilegedAction;
import java.util.*;
import java.util.regex.Pattern;
/*
* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
@@ -27,80 +77,9 @@ import javafx.fxml.*;
*
*/
import com.sun.javafx.util.Logging;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.URL;
import java.nio.charset.Charset;
import java.security.AllPermission;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.regex.Pattern;
import javafx.beans.DefaultProperty;
import javafx.beans.InvalidationListener;
import javafx.beans.property.Property;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.*;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.util.Builder;
import javafx.util.BuilderFactory;
import javafx.util.Callback;
import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.util.StreamReaderDelegate;
import com.sun.javafx.beans.IDProperty;
import com.sun.javafx.fxml.BeanAdapter;
import com.sun.javafx.fxml.LoadListener;
import com.sun.javafx.fxml.ParseTraceElement;
import com.sun.javafx.fxml.PropertyNotFoundException;
import com.sun.javafx.fxml.expression.Expression;
import com.sun.javafx.fxml.expression.ExpressionValue;
import com.sun.javafx.fxml.expression.KeyPath;
import java.net.MalformedURLException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.EnumMap;
import java.util.Locale;
import java.util.StringTokenizer;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.reflect.misc.ConstructorUtil;
import sun.reflect.misc.MethodUtil;
import sun.reflect.misc.ReflectUtil;
/**
* Loads an object hierarchy from an XML document.
*
* @since JavaFX 2.0
*/
public class FXMLLoaderPlus {
@@ -109,6 +88,16 @@ public class FXMLLoaderPlus {
private static final RuntimePermission GET_CLASSLOADER_PERMISSION =
new RuntimePermission("getClassLoader");
private boolean show = false;
public boolean isShow() {
return show;
}
public void setShow(boolean show) {
this.show = show;
}
// Abstract base class for elements
private abstract class Element {
public final cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus.Element parent;
@@ -152,14 +141,14 @@ public class FXMLLoaderPlus {
// to that (coerce to the appropriate type)
List<Object> list;
if (value instanceof List<?>) {
list = (List<Object>)value;
list = (List<Object>) value;
} else {
Class<?> type = value.getClass();
DefaultProperty defaultProperty = type.getAnnotation(DefaultProperty.class);
String defaultPropertyName = defaultProperty.value();
// Get the list value
list = (List<Object>)getProperties().get(defaultPropertyName);
list = (List<Object>) getProperties().get(defaultPropertyName);
// Coerce the element to the list item type
if (!Map.class.isAssignableFrom(type)) {
@@ -205,7 +194,7 @@ public class FXMLLoaderPlus {
@SuppressWarnings("unchecked")
public Map<String, Object> getProperties() {
return (isTyped()) ? getValueAdapter() : (Map<String, Object>)value;
return (isTyped()) ? getValueAdapter() : (Map<String, Object>) value;
}
public void processStartElement() throws IOException {
@@ -241,7 +230,7 @@ public class FXMLLoaderPlus {
}
public void processAttribute(String prefix, String localName, String value)
throws IOException{
throws IOException {
if (prefix == null) {
// Add the attribute to the appropriate list
if (localName.startsWith(EVENT_HANDLER_PREFIX)) {
@@ -314,12 +303,12 @@ public class FXMLLoaderPlus {
expression = Expression.valueOf(value);
// Create the binding
BeanAdapter targetAdapter = new BeanAdapter(this.value);
MyBeanAdapter targetAdapter = new MyBeanAdapter(this.value);
ObservableValue<Object> propertyModel = targetAdapter.getPropertyModel(attribute.name);
Class<?> type = targetAdapter.getType(attribute.name);
if (propertyModel instanceof Property<?>) {
((Property<Object>) propertyModel).bind(new ExpressionValue(namespace, expression, type));
((Property<Object>) propertyModel).bind(new MyExpressionValue(namespace, expression, type));
}
}
} else if (isBidirectionalBindingExpression(value)) {
@@ -454,7 +443,7 @@ public class FXMLLoaderPlus {
* the array becomes relative to document location.
*/
private Object populateArrayFromString(
Class<?>type,
Class<?> type,
String stringValue) throws LoadException {
Object propertyValue = null;
@@ -485,22 +474,22 @@ public class FXMLLoaderPlus {
String listPropertyName,
String stringValue) throws LoadException {
// Split the string and add the values to the list
List<Object> list = (List<Object>)valueAdapter.get(listPropertyName);
List<Object> list = (List<Object>) valueAdapter.get(listPropertyName);
Type listType = valueAdapter.getGenericType(listPropertyName);
Type itemType = (Class<?>)BeanAdapter.getGenericListItemType(listType);
Type itemType = (Class<?>) BeanAdapter.getGenericListItemType(listType);
if (itemType instanceof ParameterizedType) {
itemType = ((ParameterizedType)itemType).getRawType();
itemType = ((ParameterizedType) itemType).getRawType();
}
if (stringValue.length() > 0) {
String[] values = stringValue.split(ARRAY_COMPONENT_DELIMITER);
for (String aValue: values) {
for (String aValue : values) {
aValue = aValue.trim();
list.add(
BeanAdapter.coerce(resolvePrefixedValue(aValue),
(Class<?>)itemType));
(Class<?>) itemType));
}
}
}
@@ -518,7 +507,7 @@ public class FXMLLoaderPlus {
}
}
private Object getExpressionObject(String handlerValue) throws LoadException{
private Object getExpressionObject(String handlerValue) throws LoadException {
if (handlerValue.startsWith(EXPRESSION_PREFIX)) {
handlerValue = handlerValue.substring(EXPRESSION_PREFIX.length());
@@ -535,13 +524,13 @@ public class FXMLLoaderPlus {
return null;
}
private <T> T getExpressionObjectOfType(String handlerValue, Class<T> type) throws LoadException{
private <T> T getExpressionObjectOfType(String handlerValue, Class<T> type) throws LoadException {
Object expression = getExpressionObject(handlerValue);
if (expression != null) {
if (type.isInstance(expression)) {
return (T) expression;
}
throw constructLoadException("Error resolving \"" + handlerValue +"\" expression."
throw constructLoadException("Error resolving \"" + handlerValue + "\" expression."
+ "Does not point to a " + type.getName());
}
return null;
@@ -625,7 +614,7 @@ public class FXMLLoaderPlus {
}
private void processObservableListHandler(String handlerValue) throws LoadException {
ObservableList list = (ObservableList)value;
ObservableList list = (ObservableList) value;
if (handlerValue.startsWith(CONTROLLER_METHOD_PREFIX)) {
cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus.MethodHandler handler = getControllerMethodHandle(handlerValue, cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus.SupportedType.LIST_CHANGE_LISTENER);
if (handler != null) {
@@ -647,7 +636,7 @@ public class FXMLLoaderPlus {
}
private void processObservableMapHandler(String handlerValue) throws LoadException {
ObservableMap map = (ObservableMap)value;
ObservableMap map = (ObservableMap) value;
if (handlerValue.startsWith(CONTROLLER_METHOD_PREFIX)) {
cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus.MethodHandler handler = getControllerMethodHandle(handlerValue, cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus.SupportedType.MAP_CHANGE_LISTENER);
if (handler != null) {
@@ -669,7 +658,7 @@ public class FXMLLoaderPlus {
}
private void processObservableSetHandler(String handlerValue) throws LoadException {
ObservableSet set = (ObservableSet)value;
ObservableSet set = (ObservableSet) value;
if (handlerValue.startsWith(CONTROLLER_METHOD_PREFIX)) {
cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus.MethodHandler handler = getControllerMethodHandle(handlerValue, cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus.SupportedType.SET_CHANGE_LISTENER);
if (handler != null) {
@@ -747,7 +736,8 @@ public class FXMLLoaderPlus {
super.processStartElement();
updateValue(constructValue());
//如果是FXBaseController对象需要注入fxml
//因为如果只是单纯反射不具有FXPlus功能只有FX功能
if (value instanceof Builder<?>) {
processInstancePropertyAttributes();
} else {
@@ -761,8 +751,9 @@ public class FXMLLoaderPlus {
super.processEndElement();
// Build the value, if necessary
if (value instanceof Builder<?>) {
Builder<Object> builder = (Builder<Object>)value;
Builder<Object> builder = (Builder<Object>) value;
updateValue(builder.build());
processValue();
@@ -804,10 +795,10 @@ public class FXMLLoaderPlus {
Type itemType = BeanAdapter.getGenericListItemType(listType);
if (itemType instanceof ParameterizedType) {
itemType = ((ParameterizedType)itemType).getRawType();
itemType = ((ParameterizedType) itemType).getRawType();
}
value = BeanAdapter.coerce(value, (Class<?>)itemType);
value = BeanAdapter.coerce(value, (Class<?>) itemType);
}
}
@@ -878,7 +869,7 @@ public class FXMLLoaderPlus {
if (valueAdapter.isReadOnly(defaultPropertyName)
&& List.class.isAssignableFrom(valueAdapter.getType(defaultPropertyName))) {
List<Object> list = (List<Object>)valueAdapter.get(defaultPropertyName);
List<Object> list = (List<Object>) valueAdapter.get(defaultPropertyName);
list.add(getListValue(this, defaultPropertyName, text));
} else {
valueAdapter.put(defaultPropertyName, text.trim());
@@ -890,7 +881,7 @@ public class FXMLLoaderPlus {
@Override
public void processAttribute(String prefix, String localName, String value)
throws IOException{
throws IOException {
if (prefix != null
&& prefix.equals(FX_NAMESPACE_PREFIX)) {
if (localName.equals(FX_ID_ATTRIBUTE)) {
@@ -988,13 +979,13 @@ public class FXMLLoaderPlus {
} else if (factory != null) {
Method factoryMethod;
try {
factoryMethod = MethodUtil.getMethod(type, factory, new Class[] {});
factoryMethod = MethodUtil.getMethod(type, factory, new Class[]{});
} catch (NoSuchMethodException exception) {
throw constructLoadException(exception);
}
try {
value = MethodUtil.invoke(factoryMethod, null, new Object [] {});
value = MethodUtil.invoke(factoryMethod, null, new Object[]{});
} catch (IllegalAccessException exception) {
throw constructLoadException(exception);
} catch (InvocationTargetException exception) {
@@ -1009,12 +1000,17 @@ public class FXMLLoaderPlus {
if (value == null) {
try {
value = ReflectUtil.newInstance(type);
if (FXBaseController.class.isAssignableFrom(type)) {
value = FXControllerFactory.getFXController(type, fx_id);
} else {
value = type.newInstance();
}
} catch (InstantiationException exception) {
throw constructLoadException(exception);
} catch (IllegalAccessException exception) {
throw constructLoadException(exception);
}
}
}
@@ -1163,6 +1159,9 @@ public class FXMLLoaderPlus {
if (fields != null) {
try {
for (Field f : fields) {
if(baseController!=null) {
f.set(baseController, value);
}
f.set(controller, value);
}
} catch (IllegalAccessException exception) {
@@ -1247,7 +1246,7 @@ public class FXMLLoaderPlus {
Constructor<?> constructor = null;
try {
constructor = ConstructorUtil.getConstructor(sourceValueType, new Class[] { sourceValueType });
constructor = ConstructorUtil.getConstructor(sourceValueType, new Class[]{sourceValueType});
} catch (NoSuchMethodException exception) {
// No-op
}
@@ -1552,7 +1551,7 @@ public class FXMLLoaderPlus {
try {
scriptReader = new InputStreamReader(location.openStream(), charset);
engine.eval(scriptReader);
} catch(ScriptException exception) {
} catch (ScriptException exception) {
exception.printStackTrace();
} finally {
if (scriptReader != null) {
@@ -1572,7 +1571,7 @@ public class FXMLLoaderPlus {
if (value != null && !staticLoad) {
// Evaluate the script
try {
scriptEngine.eval((String)value);
scriptEngine.eval((String) value);
} catch (ScriptException exception) {
System.err.println(exception.getMessage());
}
@@ -1629,7 +1628,7 @@ public class FXMLLoaderPlus {
@Override
public void processAttribute(String prefix, String localName, String value)
throws LoadException{
throws LoadException {
throw constructLoadException("Element does not support attributes.");
}
}
@@ -1683,7 +1682,7 @@ public class FXMLLoaderPlus {
// Execute the script
try {
scriptEngine.eval(script);
} catch (ScriptException exception){
} catch (ScriptException exception) {
throw new RuntimeException(exception);
}
@@ -1771,7 +1770,7 @@ public class FXMLLoaderPlus {
if (type != cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus.SupportedType.PARAMETERLESS) {
MethodUtil.invoke(method, controller, params);
} else {
MethodUtil.invoke(method, controller, new Object[] {});
MethodUtil.invoke(method, controller, new Object[]{});
}
} catch (InvocationTargetException exception) {
throw new RuntimeException(exception);
@@ -1788,11 +1787,21 @@ public class FXMLLoaderPlus {
private Object root = null;
private Object controller = null;
private Object baseController = null;
private BuilderFactory builderFactory;
private Callback<Class<?>, Object> controllerFactory;
private Charset charset;
public Object getBaseController() {
return baseController;
}
public void setBaseController(Object baseController) {
this.baseController = baseController;
}
private final LinkedList<cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus> loaders;
private ClassLoader classLoader = null;
@@ -1849,6 +1858,7 @@ public class FXMLLoaderPlus {
public static final String FX_VALUE_ATTRIBUTE = "value";
/**
* The tag name of 'fx:constant'
*
* @since JavaFX 2.2
*/
public static final String FX_CONSTANT_ATTRIBUTE = "constant";
@@ -1903,11 +1913,13 @@ public class FXMLLoaderPlus {
/**
* The tag name of &lt;fx:root&gt;
*
* @since JavaFX 2.2
*/
public static final String ROOT_TAG = "root";
/**
* &lt;fx:root&gt; 'type' attribute
*
* @since JavaFX 2.2
*/
public static final String ROOT_TYPE_ATTRIBUTE = "type";
@@ -1944,6 +1956,7 @@ public class FXMLLoaderPlus {
* Escape prefix for escaping special characters inside attribute values.
* Serves as an escape for {@link #ESCAPE_PREFIX}, {@link #RELATIVE_PATH_PREFIX},
* {@link #RESOURCE_KEY_PREFIX, {@link #EXPRESSION_PREFIX}, {@link #BI_DIRECTIONAL_BINDING_PREFIX}
*
* @since JavaFX 2.1
*/
public static final String ESCAPE_PREFIX = "\\";
@@ -1970,29 +1983,34 @@ public class FXMLLoaderPlus {
/**
* Prefix for bidirectional-binding expression resolution
*
* @since JavaFX 2.1
*/
public static final String BI_DIRECTIONAL_BINDING_PREFIX = "#{";
/**
* Suffix for bidirectional-binding expression resolution
*
* @since JavaFX 2.1
*/
public static final String BI_DIRECTIONAL_BINDING_SUFFIX = "}";
/**
* Delimiter for arrays as values
*
* @since JavaFX 2.1
*/
public static final String ARRAY_COMPONENT_DELIMITER = ",";
/**
* A key for location URL in namespace map
*
* @see #getNamespace()
* @since JavaFX 2.2
*/
public static final String LOCATION_KEY = "location";
/**
* A key for ResourceBundle in namespace map
*
* @see #getNamespace()
* @since JavaFX 2.2
*/
@@ -2004,6 +2022,7 @@ public class FXMLLoaderPlus {
public static final String CONTROLLER_METHOD_PREFIX = "#";
/**
* A key for controller in namespace map
*
* @see #getNamespace()
* @since JavaFX 2.1
*/
@@ -2011,6 +2030,7 @@ public class FXMLLoaderPlus {
/**
* A suffix for controllers of included fxml files.
* The full key is stored in namespace map.
*
* @see #getNamespace()
* @since JavaFX 2.2
*/
@@ -2018,18 +2038,21 @@ public class FXMLLoaderPlus {
/**
* The name of initialize method
*
* @since JavaFX 2.2
*/
public static final String INITIALIZE_METHOD_NAME = "initialize";
/**
* Contains the current javafx version
*
* @since JavaFX 8.0
*/
public static final String JAVAFX_VERSION;
/**
* Contains the current fx namepsace version
*
* @since JavaFX 8.0
*/
public static final String FX_NAMESPACE_VERSION = "1";
@@ -2047,7 +2070,7 @@ public class FXMLLoaderPlus {
* Creates a new FXMLLoader instance.
*/
public FXMLLoaderPlus() {
this((URL)null);
this((URL) null);
}
/**
@@ -2093,7 +2116,7 @@ public class FXMLLoaderPlus {
* @since JavaFX 2.1
*/
public FXMLLoaderPlus(URL location, ResourceBundle resources, BuilderFactory builderFactory,
Callback<Class<?>, Object> controllerFactory) {
Callback<Class<?>, Object> controllerFactory) {
this(location, resources, builderFactory, controllerFactory, Charset.forName(DEFAULT_CHARSET_NAME));
}
@@ -2117,7 +2140,7 @@ public class FXMLLoaderPlus {
* @since JavaFX 2.1
*/
public FXMLLoaderPlus(URL location, ResourceBundle resources, BuilderFactory builderFactory,
Callback<Class<?>, Object> controllerFactory, Charset charset) {
Callback<Class<?>, Object> controllerFactory, Charset charset) {
this(location, resources, builderFactory, controllerFactory, charset,
new LinkedList<cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus>());
}
@@ -2134,8 +2157,8 @@ public class FXMLLoaderPlus {
* @since JavaFX 2.1
*/
public FXMLLoaderPlus(URL location, ResourceBundle resources, BuilderFactory builderFactory,
Callback<Class<?>, Object> controllerFactory, Charset charset,
LinkedList<cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus> loaders) {
Callback<Class<?>, Object> controllerFactory, Charset charset,
LinkedList<cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus> loaders) {
setLocation(location);
setResources(resources);
setBuilderFactory(builderFactory);
@@ -2189,7 +2212,7 @@ public class FXMLLoaderPlus {
*/
@SuppressWarnings("unchecked")
public <T> T getRoot() {
return (T)root;
return (T) root;
}
/**
@@ -2198,8 +2221,7 @@ public class FXMLLoaderPlus {
* must be called prior to loading the document when using
* <tt>&lt;fx:root&gt;</tt>.
*
* @param root
* The root of the object hierarchy.
* @param root The root of the object hierarchy.
* @since JavaFX 2.2
*/
public void setRoot(Object root) {
@@ -2209,7 +2231,7 @@ public class FXMLLoaderPlus {
@Override
public boolean equals(Object obj) {
if (obj instanceof cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus) {
cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus loader = (cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus)obj;
cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus loader = (cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus) obj;
if (location == null || loader.location == null) {
return loader.location == location;
}
@@ -2236,7 +2258,7 @@ public class FXMLLoaderPlus {
*/
@SuppressWarnings("unchecked")
public <T> T getController() {
return (T)controller;
return (T) controller;
}
/**
@@ -2246,8 +2268,7 @@ public class FXMLLoaderPlus {
* controller event handlers when an <tt>fx:controller</tt> attribute is not
* specified in the document.
*
* @param controller
* The controller to associate with the root object.
* @param controller The controller to associate with the root object.
* @since JavaFX 2.2
*/
public void setController(Object controller) {
@@ -2280,6 +2301,7 @@ public class FXMLLoaderPlus {
/**
* Returns the controller cn.edu.scau.biubiusuisui.factory used by this serializer.
*
* @since JavaFX 2.1
*/
public Callback<Class<?>, Object> getControllerFactory() {
@@ -2319,6 +2341,7 @@ public class FXMLLoaderPlus {
/**
* Returns the classloader used by this serializer.
*
* @since JavaFX 2.1
*/
@CallerSensitive
@@ -2365,7 +2388,6 @@ public class FXMLLoaderPlus {
* Sets the static load flag.
*
* @param staticLoad
*
* @treatAsPrivate
* @deprecated
*/
@@ -2389,7 +2411,6 @@ public class FXMLLoaderPlus {
* Sets this loader's load listener.
*
* @param loadListener
*
* @treatAsPrivate
* @deprecated
*/
@@ -2403,8 +2424,7 @@ public class FXMLLoaderPlus {
* the document will be loaded must have been set by a prior call to
* {@link #setLocation(URL)}.
*
* @return
* The loaded object hierarchy.
* @return The loaded object hierarchy.
* @since JavaFX 2.1
*/
@CallerSensitive
@@ -2417,11 +2437,8 @@ public class FXMLLoaderPlus {
/**
* Loads an object hierarchy from a FXML document.
*
* @param inputStream
* An input stream containing the FXML data to load.
*
* @return
* The loaded object hierarchy.
* @param inputStream An input stream containing the FXML data to load.
* @return The loaded object hierarchy.
*/
@CallerSensitive
public <T> T load(InputStream inputStream) throws IOException {
@@ -2451,7 +2468,7 @@ public class FXMLLoaderPlus {
return value;
}
@SuppressWarnings({ "dep-ann", "unchecked" })
@SuppressWarnings({"dep-ann", "unchecked"})
private <T> T loadImpl(InputStream inputStream,
Class<?> callerClass) throws IOException {
if (inputStream == null) {
@@ -2548,30 +2565,32 @@ public class FXMLLoaderPlus {
if (controller != null) {
if (controller instanceof Initializable) {
((Initializable)controller).initialize(location, resources);
((Initializable) controller).initialize(location, resources);
} else {
// Inject controller fields
Map<String, List<Field>> controllerFields =
controllerAccessor.getControllerFields();
if (!show) {
Map<String, List<Field>> controllerFields =
controllerAccessor.getControllerFields();
injectFields(LOCATION_KEY, location);
injectFields(LOCATION_KEY, location);
injectFields(RESOURCES_KEY, resources);
injectFields(RESOURCES_KEY, resources);
// Initialize the controller
Method initializeMethod = controllerAccessor
.getControllerMethods()
.get(cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus.SupportedType.PARAMETERLESS)
.get(INITIALIZE_METHOD_NAME);
// Initialize the controller
Method initializeMethod = controllerAccessor
.getControllerMethods()
.get(cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus.SupportedType.PARAMETERLESS)
.get(INITIALIZE_METHOD_NAME);
if (initializeMethod != null) {
try {
MethodUtil.invoke(initializeMethod, controller, new Object [] {});
} catch (IllegalAccessException exception) {
// TODO Throw when Initializable is deprecated/removed
// throw constructLoadException(cn.edu.scau.biubiusuisui.exception);
} catch (InvocationTargetException exception) {
throw constructLoadException(exception);
if (initializeMethod != null) {
try {
MethodUtil.invoke(initializeMethod, controller, new Object[]{});
} catch (IllegalAccessException exception) {
// TODO Throw when Initializable is deprecated/removed
// throw constructLoadException(cn.edu.scau.biubiusuisui.exception);
} catch (InvocationTargetException exception) {
throw constructLoadException(exception);
}
}
}
}
@@ -2588,7 +2607,7 @@ public class FXMLLoaderPlus {
xmlStreamReader = null;
}
return (T)root;
return (T) root;
}
private void clearImports() {
@@ -2596,7 +2615,7 @@ public class FXMLLoaderPlus {
classes.clear();
}
private LoadException constructLoadException(String message){
private LoadException constructLoadException(String message) {
return new LoadException(message + constructFXMLTrace());
}
@@ -2604,7 +2623,7 @@ public class FXMLLoaderPlus {
return new LoadException(constructFXMLTrace(), cause);
}
private LoadException constructLoadException(String message, Throwable cause){
private LoadException constructLoadException(String message, Throwable cause) {
return new LoadException(message + constructFXMLTrace(), cause);
}
@@ -2628,8 +2647,8 @@ public class FXMLLoaderPlus {
* Returns the current line number.
*
* @treatAsPrivate
* @deprecated
* @since JavaFX 2.2
* @deprecated
*/
public int impl_getLineNumber() {
return xmlStreamReader.getLocation().getLineNumber();
@@ -2639,8 +2658,8 @@ public class FXMLLoaderPlus {
* Returns the current parse trace.
*
* @treatAsPrivate
* @deprecated
* @since JavaFX 2.1
* @deprecated
*/
// SB-dependency: RT-21475 has been filed to track this
public ParseTraceElement[] impl_getParseTrace() {
@@ -2921,7 +2940,6 @@ public class FXMLLoaderPlus {
private static enum SupportedType {
PARAMETERLESS {
@Override
protected boolean methodIsOfType(Method m) {
return m.getParameterTypes().length == 0;
@@ -2929,7 +2947,6 @@ public class FXMLLoaderPlus {
},
EVENT {
@Override
protected boolean methodIsOfType(Method m) {
return m.getParameterTypes().length == 1 &&
@@ -2938,7 +2955,6 @@ public class FXMLLoaderPlus {
},
LIST_CHANGE_LISTENER {
@Override
protected boolean methodIsOfType(Method m) {
return m.getParameterTypes().length == 1 &&
@@ -2947,7 +2963,6 @@ public class FXMLLoaderPlus {
},
MAP_CHANGE_LISTENER {
@Override
protected boolean methodIsOfType(Method m) {
return m.getParameterTypes().length == 1 &&
@@ -2956,7 +2971,6 @@ public class FXMLLoaderPlus {
},
SET_CHANGE_LISTENER {
@Override
protected boolean methodIsOfType(Method m) {
return m.getParameterTypes().length == 1 &&
@@ -2965,7 +2979,6 @@ public class FXMLLoaderPlus {
},
PROPERTY_CHANGE_LISTENER {
@Override
protected boolean methodIsOfType(Method m) {
return m.getParameterTypes().length == 3 &&
@@ -3001,9 +3014,7 @@ public class FXMLLoaderPlus {
*
* @param packageName
* @param className
*
* @deprecated
* This method now delegates to {@link #getDefaultClassLoader()}.
* @deprecated This method now delegates to {@link #getDefaultClassLoader()}.
*/
public static Class<?> loadType(String packageName, String className) throws ClassNotFoundException {
return loadType(packageName + "." + className.replace('.', '$'));
@@ -3013,9 +3024,7 @@ public class FXMLLoaderPlus {
* Loads a type using the default class loader.
*
* @param className
*
* @deprecated
* This method now delegates to {@link #getDefaultClassLoader()}.
* @deprecated This method now delegates to {@link #getDefaultClassLoader()}.
*/
public static Class<?> loadType(String className) throws ClassNotFoundException {
ReflectUtil.checkPackageAccess(className);
@@ -3060,6 +3069,7 @@ public class FXMLLoaderPlus {
/**
* Returns the default class loader.
*
* @since JavaFX 2.1
*/
@CallerSensitive
@@ -3074,8 +3084,7 @@ public class FXMLLoaderPlus {
/**
* Sets the default class loader.
*
* @param defaultClassLoader
* The default class loader to use when loading classes.
* @param defaultClassLoader The default class loader to use when loading classes.
* @since JavaFX 2.1
*/
public static void setDefaultClassLoader(ClassLoader defaultClassLoader) {
@@ -3124,7 +3133,7 @@ public class FXMLLoaderPlus {
private static <T> T loadImpl(URL location, ResourceBundle resources,
Class<?> callerClass) throws IOException {
return loadImpl(location, resources, null,
return loadImpl(location, resources, null,
callerClass);
}
@@ -3219,10 +3228,11 @@ public class FXMLLoaderPlus {
/**
* Utility method for comparing two JavaFX version strings (such as 2.2.5, 8.0.0-ea)
*
* @param rtVer String representation of JavaFX runtime version, including - or _ appendix
* @param nsVer String representation of JavaFX version to compare against runtime version
* @return number &lt; 0 if runtime version is lower, 0 when both versions are the same,
* number &gt; 0 if runtime is higher version
* number &gt; 0 if runtime is higher version
*/
static int compareJFXVersions(String rtVer, String nsVer) {
@@ -3367,7 +3377,7 @@ public class FXMLLoaderPlus {
Map<cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus.SupportedType, Map<String, Method>> getControllerMethods() {
if (controllerMethods == null) {
controllerMethods = new EnumMap<>(cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus.SupportedType.class);
for (cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus.SupportedType t: cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus.SupportedType.values()) {
for (cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus.SupportedType t : cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus.SupportedType.values()) {
controllerMethods.put(t, new HashMap<String, Method>());
}

View File

@@ -1,38 +1,50 @@
package cn.edu.scau.biubiusuisui.config;
import cn.edu.scau.biubiusuisui.annotation.FXScan;
import cn.edu.scau.biubiusuisui.factory.FXFactory;
import cn.edu.scau.biubiusuisui.annotation.FXWindow;
import cn.edu.scau.biubiusuisui.factory.BeanBuilder;
import cn.edu.scau.biubiusuisui.factory.FXBuilder;
import cn.edu.scau.biubiusuisui.factory.FXControllerFactory;
import cn.edu.scau.biubiusuisui.function.FXWindowParser;
import cn.edu.scau.biubiusuisui.utils.ClassUtils;
import 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();
public static void start(Class clazz){
Annotation []annotations = clazz.getDeclaredAnnotations();
for(Annotation annotation : annotations){
if(FXScan.class.equals(annotation.annotationType())){
String []dirs = ((FXScan)annotation).base();
private static BeanBuilder DEFALUT_BEAN_FACTORY = new FXBuilder();
private static BeanBuilder beanBuilder;
public static boolean IS_SCENE_BUILDER = true;
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();
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);
loadFXPlusClass(className, beanBuilder);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
@@ -42,8 +54,14 @@ public class FXPlusApplication {
}
}
private static void loadFXPlusClass(String className) throws ClassNotFoundException {
public static void start(Class clazz) {
start(clazz, DEFALUT_BEAN_FACTORY);
}
private static void loadFXPlusClass(String className, BeanBuilder beanBuilder) throws ClassNotFoundException {
Class clazz = Class.forName(className);
FXFactory.loadFXController(clazz);
if (clazz.getAnnotation(FXWindow.class) != null) {
FXControllerFactory.loadStage(clazz, beanBuilder);
}
}
}

View File

@@ -1,15 +1,15 @@
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 javafx.fxml.Initializable;
import javafx.scene.layout.Pane;
import cn.edu.scau.biubiusuisui.config.FXPlusApplication;
import cn.edu.scau.biubiusuisui.utils.StringUtils;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.util.ResourceBundle;
/**
* @Author jack
@@ -17,27 +17,25 @@ import java.util.ResourceBundle;
*/
/**
* 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
@@ -46,34 +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) {
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("?");
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;
@@ -87,11 +103,20 @@ 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() {
return stage;
}
public void setStage(Stage stage) {
this.stage = stage;
}
}

View File

@@ -1,33 +0,0 @@
package cn.edu.scau.biubiusuisui.entity;
import javafx.beans.property.Property;
import javafx.beans.value.ObservableValue;
import java.lang.reflect.Method;
/**
* @Author jack
* @Date:2019/6/28 10:03
*/
public class FXFieldViewFieldMapping {
private boolean readOnly;
private Class type;
public boolean isReadOnly() {
return readOnly;
}
public void setReadOnly(boolean readOnly) {
this.readOnly = readOnly;
}
public Class getType() {
return type;
}
public void setType(Class type) {
this.type = type;
}
}

View File

@@ -0,0 +1,43 @@
package cn.edu.scau.biubiusuisui.entity;
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 FXFieldWrapper {
private FXField fxField;
private Property property;
private Class type;
public Class getType() {
return type;
}
public void setType(Class type) {
this.type = type;
}
public FXField getFxField() {
return fxField;
}
public void setFxField(FXField fxField) {
this.fxField = fxField;
}
public Property getProperty() {
return property;
}
public void setProperty(Property property){
this.property = property;
}
}

View File

@@ -1,6 +1,6 @@
package cn.edu.scau.biubiusuisui.entity;
import cn.edu.scau.biubiusuisui.proxy.classProxy.FXEntityProxy;
import cn.edu.scau.biubiusuisui.proxy.FXEntityProxy;
import javafx.beans.property.Property;
import java.util.LinkedList;
@@ -9,7 +9,6 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
*
* Context is use for storing Controller
* In addition,you can store an instance into Session to use it everywhere
*
@@ -18,62 +17,35 @@ import java.util.concurrent.ConcurrentHashMap;
*/
public class FXPlusContext {
private FXPlusContext(){}
private FXPlusContext() {
}
private static Map<String, List<FXBaseController>> controllerContext = new ConcurrentHashMap<>(); //FXController控制器注册表
private static Map<Object, FXEntityProxy> beanProxyMap = new ConcurrentHashMap<>(); // Object注册为FXEntityObject
private static Map<Object, FXEntityProxy> beanMap = new ConcurrentHashMap<>(); // Object注册为FXEntityObject
public static Property getEntityPropertyByName(Object object, String fieldName){
FXEntityProxy fxEntityProxy = FXPlusContext.getProryByBeanObject(object);
if(fxEntityProxy == null){
return null;
}
return fxEntityProxy.getStringPropertyMap().get(fieldName);
}
private static Map<String, Object> session = new ConcurrentHashMap<>();
public static void addController(FXBaseController fxBaseController){
public static void addController(FXBaseController fxBaseController) {
List<FXBaseController> controllers = controllerContext.get(fxBaseController.getName());
if(controllers == null){
if (controllers == null) {
controllers = new LinkedList<>();
}
controllers.add(fxBaseController);
}
public static List<FXBaseController> getControllers(String key){
public static List<FXBaseController> getControllers(String key) {
return controllerContext.get(key);
}
public static FXEntityProxy getProryByBeanObject(Object object){
return beanProxyMap.get(object);
public static FXEntityProxy getProxyByBeanObject(Object object) {
return beanMap.get(object);
}
public static void setProxyByBeanObject(Object object,FXEntityProxy fxEntityProxy){
beanProxyMap.put(object,fxEntityProxy);
}
public static Map<Object, FXEntityProxy> getBeanProxyMap() {
return beanProxyMap;
public static void setProxyByBeanObject(Object object, FXEntityProxy fxEntityProxy) {
beanMap.put(object, fxEntityProxy);
}
public static void setBeanProxyMap(Map<Object, FXEntityProxy> beanProxyMap) {
FXPlusContext.beanProxyMap = beanProxyMap;
}
public static Map<String, List<FXBaseController>> getControllerContext() {
return controllerContext;
}
public static void setControllerContext(Map<String, List<FXBaseController>> controllerContext) {
FXPlusContext.controllerContext = controllerContext;
}
public static Map<String, Object> getSession() {
return session;
}
public static void setSession(Map<String, Object> session) {
FXPlusContext.session = session;
public static Property getEntityPropertyByName(Object object, String fieldName) {
return getProxyByBeanObject(object).getPropertyByFieldName(fieldName);
}
}

View File

@@ -1,58 +0,0 @@
package cn.edu.scau.biubiusuisui.example;
import cn.edu.scau.biubiusuisui.annotation.FXController;
import cn.edu.scau.biubiusuisui.annotation.FXWindow;
import cn.edu.scau.biubiusuisui.entity.FXBaseController;
import cn.edu.scau.biubiusuisui.entity.FXPlusContext;
import cn.edu.scau.biubiusuisui.factory.FXEntityFactory;
import javafx.beans.property.Property;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import java.net.URL;
import java.util.ResourceBundle;
/**
* @Author jack
* @Date:2019/6/25 1:47
*/
@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;
Student student;
@FXML
void addWord(ActionEvent event) {
student.addList("hello" );
}
@FXML
void delWord(ActionEvent event) {
student.delList("hello");
}
@Override
public void initialize() {
student = (Student) FXEntityFactory.createJavaBeanProxy(Student.class);
Property property = FXPlusContext.getEntityPropertyByName(student, "list");
list.itemsProperty().bind(property);
}
}

View File

@@ -1,66 +0,0 @@
package cn.edu.scau.biubiusuisui.example;
import cn.edu.scau.biubiusuisui.annotation.FXEntity;
import cn.edu.scau.biubiusuisui.annotation.FXField;
import java.util.ArrayList;
import java.util.List;
/**
* @Author jack
* @Date:2019/6/27 20:02
*/
@FXEntity
public class Student {
@FXField
private String name;
private int age;
private String gender;
private String code;
@FXField
private List<String> list = new ArrayList<>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public void addList(String word){
list.add(word);
}
public void delList(String word){
list.remove(word);
}
}

View File

@@ -0,0 +1,18 @@
package cn.edu.scau.biubiusuisui.example.actionDemo;
import cn.edu.scau.biubiusuisui.annotation.FXScan;
import cn.edu.scau.biubiusuisui.config.FXPlusApplication;
import javafx.application.Application;
import javafx.stage.Stage;
/**
* @Author jack
* @Date:2019/7/27 1:43
*/
@FXScan(base = "cn.edu.scau.biubiusuisui.example.actionDemo")
public class Demo extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
FXPlusApplication.start(Demo.class);
}
}

View File

@@ -0,0 +1,71 @@
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.FXWindow;
import cn.edu.scau.biubiusuisui.entity.FXBaseController;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import java.net.URL;
import java.util.ResourceBundle;
/**
* @Author jack
* @Date:2019/7/27 1:43
*/
@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;
@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);
}
@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);
}
}
});
}
}

View File

@@ -0,0 +1,32 @@
package cn.edu.scau.biubiusuisui.example.actionDemo;
import cn.edu.scau.biubiusuisui.annotation.FXEntity;
import cn.edu.scau.biubiusuisui.annotation.FXField;
/**
* @Author jack
* @Date:2019/7/27 12:19
*/
@FXEntity
public class User {
@FXField
private String name;
@FXField
private String password;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

View File

@@ -0,0 +1,20 @@
package cn.edu.scau.biubiusuisui.example.firstDemo;
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 2020/1/1 23:06
* @email suiyu_yang@163.com
*/
@FXScan(base = {"cn.edu.scau.biubiusuisui.example.firstDemo"}) //会扫描带FXController和FXEntity的类进行初始化
public class Demo extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
FXPlusApplication.start(Demo.class); //其他配置和JavaFX相同这里要调用FXPlusAppcalition的start方法开始FX-plus加强
}
}

View File

@@ -0,0 +1,55 @@
package cn.edu.scau.biubiusuisui.example.firstDemo;
import cn.edu.scau.biubiusuisui.annotation.FXController;
import cn.edu.scau.biubiusuisui.annotation.FXWindow;
import cn.edu.scau.biubiusuisui.entity.FXBaseController;
import cn.edu.scau.biubiusuisui.entity.FXPlusContext;
import cn.edu.scau.biubiusuisui.factory.FXEntityFactory;
import javafx.beans.property.Property;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import java.net.URL;
import java.util.ResourceBundle;
/**
* @author suiyu_yang
* @description
* @date 2020/1/1 23:06
* @email suiyu_yang@163.com
*/
@FXController(path = "firstDemo/firstDemo.fxml")
@FXWindow(title = "firstDemo", mainStage = true)
public class MainController extends FXBaseController implements Initializable {
@FXML
private Button addHelloButton;
@FXML
private Button deleteHelloButton;
@FXML
private ListView<String> list;
private Student student;
@FXML
void addWord(ActionEvent event) {
student.addList("hello");
}
@FXML
void delWord(ActionEvent event) {
student.delList("hello");
}
@Override
public void initialize(URL location, ResourceBundle resources) {
student = (Student) FXEntityFactory.wrapFxBean(Student.class); // 从工厂中拿到将JavaBean转换得到的JavaFXBean
Property listProperty = FXPlusContext.getEntityPropertyByName(student, "list");
list.itemsProperty().bind(listProperty);
}
}

View File

@@ -0,0 +1,33 @@
package cn.edu.scau.biubiusuisui.example.firstDemo;
import cn.edu.scau.biubiusuisui.annotation.FXEntity;
import cn.edu.scau.biubiusuisui.annotation.FXField;
import java.util.ArrayList;
import java.util.List;
/**
* @author suiyu_yang
* @description
* @date 2020/1/1 23:07
* @email suiyu_yang@163.com
*/
@FXEntity
public class Student {
@FXField //标记该属性是否被生成对应的Property
private int age = 0;
@FXField
private List<String> list = new ArrayList<>();
public void addList(String word) {
list.add(word);
}
public void delList(String word) {
list.remove(word);
}
}

View File

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

View File

@@ -0,0 +1,44 @@
package cn.edu.scau.biubiusuisui.example.listDemo;
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.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.ListView;
import java.util.ArrayList;
/**
* @Author jack
* @Date:2019/7/27 1:43
*/
@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> userNameListView;
@FXML
public void addUserName() {
user.addNames("Jack\t" + (count++));
}
public ObservableList toList(ArrayList list) {
if (list == null) {
return null;
}
return FXCollections.observableList(list);
}
}

View File

@@ -0,0 +1,57 @@
package cn.edu.scau.biubiusuisui.example.listDemo;
import cn.edu.scau.biubiusuisui.annotation.FXEntity;
import cn.edu.scau.biubiusuisui.annotation.FXField;
import java.util.ArrayList;
/**
* @Author jack
* @Date:2019/7/27 12:19
*/
@FXEntity
public class User {
@FXField
private String name;
@FXField
private String password;
@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;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public ArrayList<String> getNames() {
return names;
}
public void setNames(ArrayList<String> names) {
this.names = names;
}
}

View File

@@ -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);
}
}

View File

@@ -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");
}
}

View File

@@ -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;
}
}

View File

@@ -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 {
}

View File

@@ -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";
}
}

View File

@@ -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);
}
}

View File

@@ -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";
}
}

View File

@@ -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) {
}
}

View File

@@ -0,0 +1,12 @@
package cn.edu.scau.biubiusuisui.exception;
/**
* @Author jack
* @Date:2019/7/27 3:00
*/
public class NoSuchChangeMethod extends Exception {
public NoSuchChangeMethod() {
super("No such change method");
}
}

View File

@@ -0,0 +1,9 @@
package cn.edu.scau.biubiusuisui.expression;
/**
* @Author jack
* @Date:2019/7/27 2:02
*/
public interface BindParser {
public void parse(Object target,String expression);
}

View File

@@ -0,0 +1,17 @@
package cn.edu.scau.biubiusuisui.expression.action;
import cn.edu.scau.biubiusuisui.expression.BindParser;
/**
* @Author jack
* @Date:2019/7/27 2:03
*/
public class ChangeParser implements BindParser {
@Override
public void parse(Object target, String expression) {
}
}

View File

@@ -0,0 +1,10 @@
package cn.edu.scau.biubiusuisui.expression.data;
/**
* @Author jack
* @Date:2019/7/27 20:03
*/
@FunctionalInterface
public interface ExpFunction<T,U,R>{
R apply(T t, U u);
}

View File

@@ -0,0 +1,185 @@
package cn.edu.scau.biubiusuisui.expression.data;
import cn.edu.scau.biubiusuisui.annotation.FXValue;
import cn.edu.scau.biubiusuisui.exception.NoSuchChangeMethod;
import com.sun.istack.internal.NotNull;
import com.sun.javafx.fxml.expression.Expression;
import com.sun.javafx.fxml.expression.VariableExpression;
import javafx.beans.property.Property;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.NoSuchElementException;
/**
* 将FXBind中表达式建立绑定
* 格式如下
* 语法如下:
* FXBind("S")
* S -> left=right
* left -> property
* right -> ${expression}
* expression -> bean.field
* <p>
* FXBind("text=${bean.field})
* textProperty 通过 adapter.getModelProeprty --> textProperty实例
* bean 通过namespace 获取因为bean有FXEntity标签所以返回包装过后的bean的property
* 最后
* left.bind(right)
*
* @Author jack
* @Date:2019/7/23 15:05
*/
public class ExpressionParser {
private Object namespace;
private Object targetController;
private static final String BIND_PREFIX = "${";
private static final String BIND_SUFIX = "}";
private static final String PROEPRTY = "Property";
public enum ExpressionType {
DataExpression,
ActionExpression
}
public ExpressionParser(Object namespace, Object targetController) {
this.namespace = namespace;
this.targetController = targetController;
}
public ExpressionParser(Object namespace) {
this.namespace = namespace;
}
private Property getLeftProperty(MyBeanAdapter myBeanAdapter, String key) {
return (Property) myBeanAdapter.getPropertyModel(key);
}
private static final String FUNCTION_PREFIX = "@";
private MyExpressionValue getRightExpreesion(MyBeanAdapter myBeanAdapter, String key, String rightExpression) {
Expression expression = null;
if (rightExpression.startsWith(FUNCTION_PREFIX)) {
expression = getFunctionExpression(rightExpression);
} else {
expression = Expression.valueOf(rightExpression);
}
Class clazz = myBeanAdapter.getType(key);
MyExpressionValue myExpressionValue = new MyExpressionValue(namespace, expression, clazz);
return myExpressionValue;
}
private Expression getFunctionExpression(String rightExpression) {
Expression expression = null;
int indexLeft = rightExpression.indexOf("(");
String methodName = rightExpression.substring(1,indexLeft);
int indexRight = rightExpression.indexOf(")");
String argString = rightExpression.substring(indexLeft + 1, indexRight);
String[] args = null;
if(!"".equals(argString.trim())) {
args = argString.split(",");
}
Class clazz = targetController.getClass();
Method[] methods = clazz.getMethods();
Expression[] expressions = null;
if(args!=null) {
expressions = new Expression[args.length];
for (int i = 0; i < args.length; i++) {
if (!"".equals(args[i].trim())) {
expressions[i] = Expression.valueOf(args[i]);
}
}
}
for (Method method : methods) {
if (method.getName().equals(methodName)) {
expression = new FunctionExpression(method, targetController, expressions);
}
}
return expression;
}
public void parse(Object object, @NotNull String expression) throws NoSuchChangeMethod {
//check expression
int index = expression.indexOf("=");
if (index == -1) {
return;
}
String[] items = expression.split("=");
if (items.length != 2) {
return;
}
String left = items[0];
String right = items[1];
if (left == null || right == null) {
return;
}
right = right.trim();
ExpressionType expressionType;
if (right.startsWith(BIND_PREFIX) && right.endsWith(BIND_SUFIX)) {
int length = right.length();
right = right.substring(2, length - 1);
expressionType = ExpressionType.DataExpression;
} else {
right = right.substring(1); //#changeMethod -> changeMethod
expressionType = ExpressionType.ActionExpression;
}
MyBeanAdapter myBeanAdapter = new MyBeanAdapter(object);
Property leftProperty = getLeftProperty(myBeanAdapter, left);
switch (expressionType) {
case DataExpression:
bindDataExpression(left, right, myBeanAdapter, leftProperty);
break;
case ActionExpression:
//
bindActionExpression(right, leftProperty);
}
}
private void bindActionExpression(String right, Property leftProperty) throws NoSuchChangeMethod {
Class clazz = targetController.getClass();
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (method.getName().equals(right)) {
leftProperty.addListener((observable, oldValue, newValue) -> {
try {
Object[] objects = getArgs(method, observable, newValue, oldValue);
method.invoke(targetController, objects);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
});
}
}
}
private void bindDataExpression(String left, String right, MyBeanAdapter myBeanAdapter, Property leftProperty) {
MyExpressionValue rightProperty = getRightExpreesion(myBeanAdapter, left, right);
leftProperty.bind(rightProperty);
}
public Object[] getArgs(Method method, Object... args) {
Parameter[] parameters = method.getParameters();
Object[] objects = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
FXValue annotation = parameters[i].getAnnotation(FXValue.class);
switch (annotation.value()) {
case "target":
objects[i] = args[0];
break;
case "newValue":
objects[i] = args[1];
break;
case "oldValue":
objects[i] = args[2];
break;
}
}
return objects;
}
}

View File

@@ -0,0 +1,85 @@
package cn.edu.scau.biubiusuisui.expression.data;
import com.sun.javafx.fxml.expression.Expression;
import com.sun.javafx.fxml.expression.KeyPath;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/**
* @Author jack
* @Date:2019/7/27 20:00
*/
public class FunctionExpression extends Expression {
private Method method;
private Object target;
private Expression []args;
public FunctionExpression(Method method, Object target, Expression[]expressions) {
this.method = method;
this.target = target;
this.args = expressions;
}
@Override
public List<KeyPath> getArguments() {
List<KeyPath> list = new ArrayList<>();
if(args !=null) {
for (Expression expression : args) {
list.addAll(expression.getArguments());
}
}
return list;
}
@Override
public Object evaluate(Object namespace) {
Object result = null;
if(args!=null){
Object[] values = new Object[args.length];
for(int i = 0 ;i<args.length;i++){
values[i] = args[i].evaluate(namespace);
}
try {
result = method.invoke(target, values);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return result;
}else{
try {
result = method.invoke(target);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
return result;
}
@Override
public void update(Object namespace, Object value) {
}
@Override
public boolean isDefined(Object namespace) {
return false;
}
@Override
public boolean isLValue() {
return false;
}
@Override
protected void getArguments(List arguments) {
}
}

View File

@@ -0,0 +1,39 @@
package cn.edu.scau.biubiusuisui.expression.data;
import cn.edu.scau.biubiusuisui.annotation.FXEntity;
import cn.edu.scau.biubiusuisui.entity.FXPlusContext;
import cn.edu.scau.biubiusuisui.utils.BeanUtil;
import com.sun.javafx.fxml.BeanAdapter;
import javafx.beans.value.ObservableValue;
/**
* @Author jack
* @Date:2019/7/23 15:16
*/
public class MyBeanAdapter extends BeanAdapter {
private Object object;
/**
* Creates a new Bean adapter.
*
* @param bean The Bean object to wrap.
*/
public MyBeanAdapter(Object bean) {
super(bean);
this.object = bean;
}
@Override
public <T> ObservableValue<T> getPropertyModel(String key) {
if (object.getClass().getAnnotation(FXEntity.class) == null) {
return super.getPropertyModel(key);
} else {
return BeanUtil.getPropertyByName(object, key);
}
}
public String valueOf(String value) {
return value;
}
}

View File

@@ -0,0 +1,220 @@
package cn.edu.scau.biubiusuisui.expression.data;
import com.sun.javafx.fxml.BeanAdapter;
import com.sun.javafx.fxml.expression.Expression;
import com.sun.javafx.fxml.expression.KeyPath;
import javafx.beans.InvalidationListener;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.beans.value.ObservableValueBase;
import javafx.collections.ListChangeListener;
import javafx.collections.MapChangeListener;
import javafx.collections.ObservableList;
import javafx.collections.ObservableMap;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class MyExpressionValue extends ObservableValueBase<Object> {
// Monitors a namespace for changes along a key path
private class KeyPathMonitor {
private String key;
private KeyPathMonitor next;
private Object namespace = null;
private ListChangeListener<Object> listChangeListener = new ListChangeListener<Object>() {
@Override
public void onChanged(Change<? extends Object> change) {
while (change.next()) {
int index = Integer.parseInt(key);
if (index >= change.getFrom() && index < change.getTo()) {
fireValueChangedEvent();
remonitor();
}
}
}
};
private MapChangeListener<String, Object> mapChangeListener = new MapChangeListener<String, Object>() {
@Override
public void onChanged(Change<? extends String, ? extends Object> change) {
if (key.equals(change.getKey())) {
fireValueChangedEvent();
remonitor();
}
}
};
private ChangeListener<Object> propertyChangeListener = new ChangeListener<Object>() {
@Override
public void changed(ObservableValue<? extends Object> observable, Object oldValue, Object newValue) {
fireValueChangedEvent();
remonitor();
}
};
public KeyPathMonitor(Iterator<String> keyPathIterator) {
this.key = keyPathIterator.next();
if (keyPathIterator.hasNext()) {
next = new KeyPathMonitor(keyPathIterator);
} else {
next = null;
}
}
@SuppressWarnings("unchecked")
public void monitor(Object namespace) {
if (namespace instanceof ObservableList<?>) {
((ObservableList<Object>)namespace).addListener(listChangeListener);
} else if (namespace instanceof ObservableMap<?, ?>) {
((ObservableMap<String, Object>)namespace).addListener(mapChangeListener);
} else {
MyBeanAdapter namespaceAdapter = new MyBeanAdapter(namespace);
ObservableValue<Object> propertyModel = namespaceAdapter.getPropertyModel(key);
if (propertyModel != null) {
propertyModel.addListener(propertyChangeListener);
}
namespace = namespaceAdapter;
}
this.namespace = namespace;
if (next != null) {
Object value = Expression.get(namespace, key);
if (value != null) {
next.monitor(value);
}
}
}
@SuppressWarnings("unchecked")
public void unmonitor() {
if (namespace instanceof ObservableList<?>) {
((ObservableList<Object>)namespace).removeListener(listChangeListener);
} else if (namespace instanceof ObservableMap<?, ?>) {
((ObservableMap<String, Object>)namespace).removeListener(mapChangeListener);
} else if (namespace != null) {
MyBeanAdapter namespaceAdapter = (MyBeanAdapter)namespace;
ObservableValue<Object> propertyModel = namespaceAdapter.getPropertyModel(key);
if (propertyModel != null) {
propertyModel.removeListener(propertyChangeListener);
}
}
namespace = null;
if (next != null) {
next.unmonitor();
}
}
public void remonitor() {
if (next != null) {
next.unmonitor();
Object value = Expression.get(namespace, key);
if (value != null) {
next.monitor(value);
}
}
}
}
private Object namespace;
private Expression expression;
private Class<?> type;
private ArrayList<KeyPathMonitor> argumentMonitors;
private int listenerCount = 0;
public MyExpressionValue(Object namespace, Expression expression, Class<?> type) {
if (namespace == null) {
throw new NullPointerException();
}
if (expression == null) {
throw new NullPointerException();
}
if (type == null) {
throw new NullPointerException();
}
this.namespace = namespace;
this.expression = expression;
this.type = type;
List<KeyPath> arguments = expression.getArguments();
argumentMonitors = new ArrayList<KeyPathMonitor>(arguments.size());
for (KeyPath argument : arguments) {
argumentMonitors.add(new KeyPathMonitor(argument.iterator()));
}
}
@Override
public Object getValue() {
return BeanAdapter.coerce(expression.evaluate(namespace), type);
}
@Override
public void addListener(InvalidationListener listener) {
if (listenerCount == 0) {
monitorArguments();
}
super.addListener(listener);
listenerCount++;
}
@Override
public void removeListener(InvalidationListener listener) {
super.removeListener(listener);
listenerCount--;
if (listenerCount == 0) {
unmonitorArguments();
}
}
@Override
public void addListener(ChangeListener<? super Object> listener) {
if (listenerCount == 0) {
monitorArguments();
}
super.addListener(listener);
listenerCount++;
}
@Override
public void removeListener(ChangeListener<? super Object> listener) {
super.removeListener(listener);
listenerCount--;
if (listenerCount == 0) {
unmonitorArguments();
}
}
private void monitorArguments() {
for (KeyPathMonitor argumentMonitor : argumentMonitors) {
argumentMonitor.monitor(namespace);
}
}
private void unmonitorArguments() {
for (KeyPathMonitor argumentMonitor : argumentMonitors) {
argumentMonitor.unmonitor();
}
}
}

View File

@@ -0,0 +1,14 @@
package cn.edu.scau.biubiusuisui.factory;
/**
* @Author jack
* @Date:2019/7/4 11:16
*/
public interface BeanBuilder {
/**
* 万能工厂方法
* @param type 类型
* @return 实例对象
*/
Object getBean(Class type);
}

View File

@@ -0,0 +1,20 @@
package cn.edu.scau.biubiusuisui.factory;
/**
* @Author jack
* @Date:2019/7/4 11:13
*/
public class FXBuilder implements BeanBuilder{
@Override
public Object getBean(Class type) {
Object object = null;
try {
object = type.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return object;
}
}

View File

@@ -0,0 +1,322 @@
package cn.edu.scau.biubiusuisui.factory;
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.config.FXMLLoaderPlus;
import cn.edu.scau.biubiusuisui.entity.FXBaseController;
import cn.edu.scau.biubiusuisui.entity.FXPlusContext;
import cn.edu.scau.biubiusuisui.exception.NoSuchChangeMethod;
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.reflect.Field;
import java.net.URL;
/**
* @Author jack
* @Date:2019/6/25 8:12
*/
public class FXControllerFactory {
private static final BeanBuilder BEAN_BUILDER = new FXBuilder();
private static FXWindowParser windowAnnotationParser = new FXWindowParser();
/**
* 控制类的注入流程
* 这是一个即将被创建的控制类
* <pre>
* <code>
* class MainController{
* @Autowired
* Student stu; //普通属性
* @FXML
* Button btn; //FX属性
* }
* </code>
* </pre>
* 1. 实现对普通属性的注入
* 如果使用了Spring那么这类会自动注入那些@Autowired的属性请不要将这个方法用在控制器属性中
* <pre>
* <code>
* class MainController{
* @Autowired
* Student stu ; //初始化完成
* @FXML
* Button btn; // null
* }
* </code>
* </pre>
* 2. 通过loadFXML实现对FX属性的注入
* <pre>
* <code>
* class MainController{
* @Autowired
* Student stu ; //初始化完成
* @FXML
* Button btn; // 初始化完成
* }
* </code>
* </pre>
* <p>
* 3. 完成对FXBind的注解的解析
* <p>
* <p>
* <p>
* 4. 完成注册
*
* @param clazz instance that extends by FXBaseController
* @param controllerName
* @return
*/
private static FXBaseController getFxBaseController(Class clazz, String controllerName, BeanBuilder beanBuilder) {
return getFxBaseController0(clazz, controllerName, beanBuilder);
}
private static FXBaseController getFxBaseController0(Class clazz, String controllerName, BeanBuilder beanBuilder) {
URL fxmlPath;
FXController fxController = null; //reflect and get FXController cn.edu.scau.biubiusuisui.annotation
fxController = (FXController) clazz.getDeclaredAnnotation(FXController.class);
Pane parent = null;
FXBaseController fxBaseController = null;
FXBaseController fxControllerProxy = null;
if (fxController != null) {
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); //产生代理从而实现赋能
fxmlLoader.setRoot(fxControllerProxy);
fxmlLoader.setController(fxControllerProxy);
fxmlLoader.setBaseController(fxBaseController);
try {
parent = fxmlLoader.load();
if (controllerName != null) {
fxControllerProxy.setName(controllerName);
fxBaseController.setName(controllerName);
} else {
fxBaseController.setName(parent.getId());
}
ObservableMap namespace = fxmlLoader.getNamespace();
addDataInNameSpace(namespace, fxBaseController); //处理fxBaseController里面的@FXData
scanBind(namespace, fxBaseController); //处理@FXBind
register(fxBaseController, fxControllerProxy);
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
} else {
return null;
}
return fxControllerProxy;
}
/**
* 将代理对象和目标对象注册
*
* @param fxBaseController 目标对象
* @param fxBaseControllerProxy 代理对象
*/
private static void register(FXBaseController fxBaseController, FXBaseController fxBaseControllerProxy) {
FXPlusContext.addController(fxBaseController); //保存
MessageQueue.getInstance().registerConsumer(fxBaseController, fxBaseControllerProxy); // 添加进入消息队列 信号功能
}
/**
* 为有FXWindow注解的类创建Stage
*
* @param fxWindow
* @param fxBaseControllerProxy
* @return
*/
private static Stage createWindow(FXWindow fxWindow, FXBaseController fxBaseControllerProxy) {
Stage stage = new Stage();
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, fxBaseControllerProxy, fxWindow);
StageManager.getInstance().registerWindow(fxBaseControllerProxy); //注册舞台
if (fxWindow.mainStage() == true) { //当是主舞台时先show为敬
// System.out.println("FXControllerFactory: "+(fxControllerProxy.getStage() == null));
fxBaseControllerProxy.showStage();
}
return stage;
}
private FXControllerFactory() {
}
/**
* 加载舞台
* 原函数名为loadMainStage(Class clazz, BeanBuilder beanBuilder)
*
* @param clazz
* @param beanBuilder
*/
public static void loadStage(Class clazz, BeanBuilder beanBuilder) {
FXWindow declaredAnnotation = (FXWindow) clazz.getDeclaredAnnotation(FXWindow.class);
//只有当用了FXWindow注解才会注册Stage
if (declaredAnnotation != null) {
getFXWindow(clazz, null, beanBuilder);
}
}
public static FXBaseController getFXController(Class clazz) {
return getFXController(clazz, BEAN_BUILDER);
}
public static FXBaseController getFXController(Class clazz, BeanBuilder beanBuilder) {
FXBaseController fxBaseController = getFXController(clazz, null, beanBuilder);
return fxBaseController;
}
public static FXBaseController getFXController(Class clazz, String controllerName) {
return getFXController(clazz, controllerName, BEAN_BUILDER);
}
public static FXBaseController getFXController(Class clazz, String controllerName, BeanBuilder beanBuilder) {
FXBaseController fxBaseController = getFxBaseController(clazz, controllerName, beanBuilder);
return fxBaseController;
}
public static Stage getFXWindow(Class clazz) {
FXWindow fxWindow = (FXWindow) clazz.getDeclaredAnnotation(FXWindow.class);
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 {
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);
if (annotation != null) {
field.setAccessible(true);
//建立代理
try {
Object fieldValue = field.get(fxControllerObject);
Object fieldValueProxy = FXEntityFactory.wrapFxBean(fieldValue);
field.set(fxControllerObject, fieldValueProxy);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
private static void addDataInNameSpace(ObservableMap namespace, Object object) {
Class clazz = object.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
FXData annotation = field.getAnnotation(FXData.class);
if (annotation != null) {
field.setAccessible(true);
try {
String fx_id;
field.setAccessible(true);
if ("".equals(annotation.fx_id())) {
fx_id = field.getName();
} else {
fx_id = annotation.fx_id();
}
Object fieldValue = field.get(object);
namespace.put(fx_id, fieldValue);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
private static void scanBind(ObservableMap namespace, Object object) {
Class clazz = object.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
parseBind(namespace, object, field);
}
}
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);
if (fxBind != null) {
String[] expressions = fxBind.value();
try {
Object objectValue = field.get(object);
for (String e : expressions) {
expressionParser.parse(objectValue, e);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchChangeMethod noSuchChangeMethod) {
noSuchChangeMethod.printStackTrace();
}
}
}
private static boolean isFXWindow(Class clazz) {
if (clazz.getDeclaredAnnotation(FXWindow.class) != null) {
return true;
} else {
return false;
}
}
}

View File

@@ -1,9 +1,9 @@
package cn.edu.scau.biubiusuisui.factory;
import cn.edu.scau.biubiusuisui.annotation.FXField;
import cn.edu.scau.biubiusuisui.entity.FXFieldViewFieldMapping;
import cn.edu.scau.biubiusuisui.entity.FXFieldWrapper;
import cn.edu.scau.biubiusuisui.entity.FXPlusContext;
import cn.edu.scau.biubiusuisui.proxy.classProxy.FXEntityProxy;
import cn.edu.scau.biubiusuisui.proxy.FXEntityProxy;
import cn.edu.scau.biubiusuisui.utils.ClassUtils;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
@@ -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,26 +20,29 @@ import java.util.List;
*/
public class FXEntityFactory {
private FXEntityFactory(){}
public static Object createJavaBeanProxy(Class clazz) {
Object object = null;
try {
object = clazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return createJavaBeanProxy(object);
private FXEntityFactory() {
}
public static Object createJavaBeanProxy(Object object){
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 wrapFxBean(object);
} else {
return null;
}
}
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();
@@ -47,34 +50,27 @@ public class FXEntityFactory {
return objectProxy;
}
public static void processFXEntityProxy(Object entity, Object proxy,FXEntityProxy fxEntityProxy) throws IllegalAccessException {
Map<String, Property> stringPropertyMap = new HashMap<>();
Map<String, FXFieldViewFieldMapping> stringFXFieldMethodMappingMap = 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;
FXFieldViewFieldMapping fieldMethodMapping = new FXFieldViewFieldMapping();
fieldMethodMapping.setReadOnly(fxField.readOnly());
fieldMethodMapping.setType(field.getType());
stringFXFieldMethodMappingMap.put(field.getName(), fieldMethodMapping);
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 = getFieldDefaultProperty(field);
} else {
property = getFieldProperty(entity, field);
}
if(property !=null) {
//添加时间;
property.addListener((object,oldVal,newVal)->{
if(!fxField.readOnly()) {
if(!field.getType().equals(List.class)) {
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) {
@@ -83,60 +79,63 @@ public class FXEntityFactory {
}
}
});
stringPropertyMap.put(field.getName(), property);
}
fieldWrapper.setProperty(property);
fxFieldWrapperMap.put(field.getName(), fieldWrapper);
}
}
fxEntityProxy.setStringPropertyMap(stringPropertyMap);
fxEntityProxy.setStringFXFieldMethodMappingMap(stringFXFieldMethodMappingMap);
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)){
if (Boolean.class.equals(type) || boolean.class.equals(type)) {
property = new SimpleBooleanProperty((Boolean) value);
}else if(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)){
} else if (Float.class.equals(type) || float.class.equals(type)) {
property = new SimpleFloatProperty((Float) value);
}else if(Integer.class.equals(type)){
} else if (Integer.class.equals(type) || int.class.equals(type)) {
property = new SimpleIntegerProperty((Integer) value);
}else if(Long.class.equals(type)){
} 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.equals(type)){
property = new SimpleListProperty(FXCollections.observableList((List)value));
}else if(Object.class.equals(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 getFieldDefaultProperty(Field field) throws IllegalAccessException {
Class type = field.getType();
Property property = null;
if(Boolean.class.equals(type)){
if (Boolean.class.equals(type) || boolean.class.equals(type)) {
property = new SimpleBooleanProperty();
}else if(Double.class.equals(type)){
} else if (Double.class.equals(type) || double.class.equals(type)) {
property = new SimpleDoubleProperty();
}else if (Float.class.equals(type)){
} else if (Float.class.equals(type) || float.class.equals(type)) {
property = new SimpleFloatProperty();
}else if(Integer.class.equals(type)){
} else if (Integer.class.equals(type) || int.class.equals(type)) {
property = new SimpleIntegerProperty();
}else if(Long.class.equals(type)){
} 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.equals(type)){
} else if (List.class.isAssignableFrom(type)) {
property = new SimpleListProperty();
}else if(Object.class.equals(type)){
} else if (Object.class.isAssignableFrom(type)) {
property = new SimpleObjectProperty();
}
return property;
}
}

View File

@@ -1,118 +0,0 @@
package cn.edu.scau.biubiusuisui.factory;
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.entity.FXBaseController;
import cn.edu.scau.biubiusuisui.entity.FXPlusContext;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import cn.edu.scau.biubiusuisui.messageQueue.MessageQueue;
import cn.edu.scau.biubiusuisui.proxy.classProxy.FXControllerProxy;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.URL;
/**
* @Author jack
* @Date:2019/6/25 8:12
*/
public class FXFactory {
private FXFactory() {
}
public static void loadFXController(Class clazz) {
getFXController(clazz, "");
}
public static FXBaseController getFXController(Class clazz) {
FXBaseController fxBaseController = getFXController(clazz, "");
return fxBaseController;
}
public static FXBaseController getFXController(Class clazz, String controllerName) {
FXBaseController fxBaseController = getFxBaseController(clazz, controllerName);
return fxBaseController;
}
private static void register(FXBaseController fxBaseController, FXBaseController fxBaseControllerProxy) {
FXPlusContext.addController(fxBaseController);
MessageQueue.getInstance().registerCosumer(fxBaseController, fxBaseControllerProxy);
}
/**
*
* @param clazz instance that extends by FXBaseController
* @param controllerName
* @return
*/
private static FXBaseController getFxBaseController(Class clazz, String controllerName) {
Annotation[] annotations = clazz.getAnnotations();
Boolean isController = false;
URL fxmlPath;
Boolean isWindow = false;
FXWindow fxWindow = null;
FXController fxController = null;
//reflect and get FXController cn.edu.scau.biubiusuisui.annotation
for (Annotation annotation : annotations) {
if (annotation.annotationType().equals(FXController.class)) {
fxController = (FXController) annotation;
isController = true;
} else if (annotation.annotationType().equals(FXWindow.class)) {
fxWindow = (FXWindow) annotation;
isWindow = true;
}
}
Pane parent = null;
FXBaseController fxControllerProxy = null;
FXBaseController fxBaseController = null;
if (isController) {
String name = fxController.path();
fxmlPath = clazz.getClassLoader().getResource(name);
FXMLLoaderPlus fxmlLoader = new FXMLLoaderPlus(fxmlPath);
try {
// create a cn.edu.scau.biubiusuisui.proxy for monitoring methods
fxBaseController = (FXBaseController) clazz.newInstance();
FXControllerProxy controllerProxy = new FXControllerProxy();
fxControllerProxy = (FXBaseController) controllerProxy.getInstance(fxBaseController);
fxControllerProxy.setName(controllerName);
fxBaseController.setName(controllerName);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
fxmlLoader.setRoot(fxControllerProxy);
fxmlLoader.setController(fxControllerProxy);
try {
parent = fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}else{
return null;
}
//register
register(fxBaseController, fxControllerProxy);
if (isWindow) {
Stage stage = new Stage();
double preWidth = fxWindow.preWidth() == 0 ? parent.getPrefWidth() : fxWindow.preWidth();
double preHeight = fxWindow.preHeight() == 0 ? parent.getPrefWidth() : fxWindow.preHeight();
Scene scene = new Scene(fxControllerProxy, preWidth, preHeight);
stage.setScene(scene);
stage.setTitle(fxWindow.title());
stage.show();
}
return fxControllerProxy;
}
}

View File

@@ -1,19 +0,0 @@
package cn.edu.scau.biubiusuisui.function;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
/**
* @Author jack
* @Date:2019/6/28 15:57
*/
public class DefaultEventFunction implements ChangeListener {
public DefaultEventFunction() {}
@Override
public void changed(ObservableValue observable, Object oldValue, Object newValue) {
}
}

View File

@@ -0,0 +1,119 @@
package cn.edu.scau.biubiusuisui.function;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
/**
* @Author jack
* @Date:2019/6/30 10:11
*/
public class DragWindowHandlerImpl implements EventHandler<MouseEvent> {
//参考<a href="https://www.cnblogs.com/moonlightL/p/5982679.html"></a>
private Stage stage; //primaryStage为start方法头中的Stage
private double oldStageX;
private double oldStageY;
private double oldScreenX;
private double oldScreenY;
final int RESIZE_WIDTH = 5;// 判定是否为调整窗口状态的范围与边界距离
private double MIN_WIDTH = 300;// 窗口最小宽度
private double MIN_HEIGHT = 250;// 窗口最小高度
boolean isRight;// 是否处于右边界调整窗口状态
boolean isBottomRight;// 是否处于右下角调整窗口状态
boolean isBottom;// 是否处于下边界调整窗口状态
private Pane pane;
private boolean fix = false;
public DragWindowHandlerImpl(Stage primaryStage, Pane pane,boolean fix) { //构造器
this.stage = primaryStage;
this.pane = pane;
this.fix = fix;
}
public DragWindowHandlerImpl(Stage stage, double MIN_WIDTH, double MIN_HEIGHT, Pane pane, boolean fix) {
this.stage = stage;
this.MIN_WIDTH = MIN_WIDTH;
this.MIN_HEIGHT = MIN_HEIGHT;
this.pane = pane;
this.fix = fix;
}
@Override
public void handle(MouseEvent e) {
if (e.getEventType() == MouseEvent.MOUSE_PRESSED) { //鼠标按下的事件
this.oldStageX = this.stage.getX();
this.oldStageY = this.stage.getY();
this.oldScreenX = e.getScreenX();
this.oldScreenY = e.getScreenY();
} else if (e.getEventType() == MouseEvent.MOUSE_DRAGGED) { //鼠标拖动的事件
//
double nextX = stage.getX();
double nextY = stage.getY();
double nextWidth = stage.getWidth();
double nextHeight = stage.getHeight();
if(!fix) {
double x = e.getSceneX();
double y = e.getSceneY();
// 保存窗口改变后的x、y坐标和宽度、高度用于预判是否会小于最小宽度、最小高度
if (isRight || isBottomRight) {// 所有右边调整窗口状态
nextWidth = x;
}
if (isBottomRight || isBottom) {// 所有下边调整窗口状态
nextHeight = y;
}
if (nextWidth <= MIN_WIDTH) {// 如果窗口改变后的宽度小于最小宽度,则宽度调整到最小宽度
nextWidth = MIN_WIDTH;
}
if (nextHeight <= MIN_HEIGHT) {// 如果窗口改变后的高度小于最小高度,则高度调整到最小高度
nextHeight = MIN_HEIGHT;
}
}
// 最后统一改变窗口的x、y坐标和宽度、高度可以防止刷新频繁出现的屏闪情况
if(isBottom ||isBottomRight ||isRight) {
stage.setX(nextX);
stage.setY(nextY);
stage.setWidth(nextWidth);
stage.setHeight(nextHeight);
}else {
this.stage.setX(e.getScreenX() - this.oldScreenX + this.oldStageX);
this.stage.setY(e.getScreenY() - this.oldScreenY + this.oldStageY);
}
} else if (e.getEventType() == MouseEvent.MOUSE_MOVED) {
if(!fix) {
e.consume();
double x = e.getSceneX();
double y = e.getSceneY();
double width = stage.getWidth();
double height = stage.getHeight();
Cursor cursorType = Cursor.DEFAULT;// 鼠标光标初始为默认类型,若未进入调整窗口状态,保持默认类型
// 先将所有调整窗口状态重置
isRight = isBottomRight = isBottom = false;
if (y >= height - RESIZE_WIDTH) {
if (x <= RESIZE_WIDTH) {// 左下角调整窗口状态
} else if (x >= width - RESIZE_WIDTH) {// 右下角调整窗口状态
isBottomRight = true;
cursorType = Cursor.SE_RESIZE;
} else {// 下边界调整窗口状态
isBottom = true;
cursorType = Cursor.S_RESIZE;
}
} else if (x >= width - RESIZE_WIDTH) {// 右边界调整窗口状态
isRight = true;
cursorType = Cursor.E_RESIZE;
}
// 最后改变鼠标光标
pane.setCursor(cursorType);
}
}
}
}

View File

@@ -0,0 +1,9 @@
package cn.edu.scau.biubiusuisui.function;
/**
* @Author jack
* @Date:2019/7/27 1:54
*/
public interface Draggale {
}

View File

@@ -0,0 +1,31 @@
package cn.edu.scau.biubiusuisui.function;
import cn.edu.scau.biubiusuisui.annotation.FXWindow;
import javafx.event.EventHandler;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
/**
* @Author jack
* @Date:2019/6/30 10:40
*/
public class FXWindowParser {
public void parse(Stage stage, Pane fxControllerProxy, FXWindow fxWindow) {
stage.setTitle(fxWindow.title());
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());
fxControllerProxy.setOnMousePressed(dragWindowHandler);
fxControllerProxy.setOnMouseDragged(dragWindowHandler);
fxControllerProxy.setOnMouseMoved(dragWindowHandler);
}
stage.initStyle(fxWindow.style());
}
}

View File

@@ -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,11 +54,12 @@ 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) {
Method method = fxMethodEntity.getMethod();
method.setAccessible(true);
FXBaseController fxBaseController = fxMethodEntity.getFxBaseController();
if (method.getParameterCount() == 0) {
try {

View File

@@ -0,0 +1,83 @@
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 cn.edu.scau.biubiusuisui.stage.StageManager;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.annotation.Annotation;
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
*
* @Author jack
* @Date:2019/6/25 2:03
*/
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);
Object proxy = enhancer.create();
// target.* -> proxy.*
inject(target, proxy);
return proxy;
}
@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;
// 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);
}
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) {
Class clazz = target.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
try {
Object value = field.get(target);
field.set(proxy, value);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}

View File

@@ -1,6 +1,6 @@
package cn.edu.scau.biubiusuisui.proxy.classProxy;
package cn.edu.scau.biubiusuisui.proxy;
import cn.edu.scau.biubiusuisui.entity.FXFieldViewFieldMapping;
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,9 +17,7 @@ import java.util.Map;
public class FXEntityProxy implements MethodInterceptor {
Object target;
private Map<String, Property> stringPropertyMap;
private Map<String, FXFieldViewFieldMapping> stringFXFieldMethodMappingMap;
private Map<String, FXFieldWrapper> fxFieldWrapperMap;
public Object getInstance(Object target) {
this.target = target;
@@ -41,32 +39,30 @@ 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;
}
FXFieldViewFieldMapping fieldMethodMapping = stringFXFieldMethodMappingMap.get(fieldName);
Property property = stringPropertyMap.get(fieldName);
if(fieldMethodMapping == null || property == null){
FXFieldWrapper fxFieldWrapper = fxFieldWrapperMap.get(fieldName);
Property property = getPropertyByFieldName(fieldName);
if (fxFieldWrapper == null || property == null) {
return o1;
}
Class type = fieldMethodMapping.getType();
Class type = fxFieldWrapper.getType();
if (methodName.startsWith("set")) {
if(Boolean.class.equals(type)){
if(Boolean.class.equals(type) || boolean.class.equals(type)){
((SimpleBooleanProperty)property).set((Boolean)objects[0]);
}else if(Double.class.equals(type)){
}else if(Double.class.equals(type)||double.class.equals(type)){
((SimpleDoubleProperty)property).set((Double)objects[0]);
}else if (Float.class.equals(type)){
}else if (Float.class.equals(type) || float.class.equals(type)){
((SimpleFloatProperty)property).set((Float) objects[0]);
}else if(Integer.class.equals(type)){
}else if(Integer.class.equals(type) || int.class.equals(type)){
((SimpleIntegerProperty)property).set((Integer) objects[0]);
}else if(Long.class.equals(type)){
}else if(Long.class.equals(type) ||long.class.equals(type)){
((SimpleLongProperty)property).set((Long)objects[0]);
}else if(String.class.equals(type)){
((SimpleStringProperty)property).set((String)objects[0]);
@@ -75,9 +71,9 @@ public class FXEntityProxy implements MethodInterceptor {
((SimpleListProperty)(property)).add(objects[0]);
}else if(methodName.startsWith("del")){
((SimpleListProperty)(property)).remove(objects[0]);
}else if(methodName.startsWith("cls")){
((SimpleListProperty)(property)).clear();
}
//修改
return o1;
}
@@ -90,22 +86,17 @@ public class FXEntityProxy implements MethodInterceptor {
}
public Property getPropertyByFieldName(String name) {
return stringPropertyMap.get(name);
if (fxFieldWrapperMap.get(name) == null) {
return null;
}
return fxFieldWrapperMap.get(name).getProperty();
}
public Map<String, Property> getStringPropertyMap() {
return stringPropertyMap;
public Map<String, FXFieldWrapper> getFxFieldWrapperMap() {
return fxFieldWrapperMap;
}
public void setStringPropertyMap(Map<String, Property> stringPropertyMap) {
this.stringPropertyMap = stringPropertyMap;
}
public Map<String, FXFieldViewFieldMapping> getStringFXFieldMethodMappingMap() {
return stringFXFieldMethodMappingMap;
}
public void setStringFXFieldMethodMappingMap(Map<String, FXFieldViewFieldMapping> stringFXFieldMethodMappingMap) {
this.stringFXFieldMethodMappingMap = stringFXFieldMethodMappingMap;
public void setFxFieldWrapperMap(Map<String, FXFieldWrapper> fxFieldWrapperMap) {
this.fxFieldWrapperMap = fxFieldWrapperMap;
}
}

View File

@@ -1,53 +0,0 @@
package cn.edu.scau.biubiusuisui.proxy.classProxy;
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.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
/**
*
* This proxy class intercept Methods that has special annotation such as
* FXSender which is a mark for message queue
*
* @Author jack
* @Date:2019/6/25 2:03
*/
public class FXControllerProxy implements MethodInterceptor {
FXBaseController target;
public Object getInstance(FXBaseController target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@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();
}
MessageQueue.getInstance().sendMsg(name,o1);
}
}
return o1;
}
}

View File

@@ -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();
}
}

View File

@@ -0,0 +1,19 @@
package cn.edu.scau.biubiusuisui.utils;
import cn.edu.scau.biubiusuisui.entity.FXPlusContext;
import cn.edu.scau.biubiusuisui.proxy.FXEntityProxy;
import javafx.beans.property.Property;
/**
* @Author jack
* @Date:2019/7/28 1:52
*/
public class BeanUtil {
public static Property getPropertyByName(Object entity, String fieldName){
FXEntityProxy fxEntityProxy = FXPlusContext.getProxyByBeanObject(entity);
if(fxEntityProxy == null){
return null;
}
return fxEntityProxy.getFxFieldWrapperMap().get(fieldName).getProperty();
}
}

View File

@@ -2,6 +2,7 @@ package cn.edu.scau.biubiusuisui.utils;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.Arrays;
import java.util.LinkedList;
@@ -12,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);
}
}
@@ -48,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();
@@ -62,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;
@@ -71,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;
@@ -79,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)) {
@@ -97,4 +100,15 @@ public class ClassUtils {
}
return null;
}
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.setAccessible(true);
// Field field1 = targetClass.getField(field.getName());
}
}
}

View File

@@ -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;
}

View File

@@ -1,13 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.text.Font?>
<fx:root prefHeight="400.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.MainController">
<children>
<Button fx:id="addBtn" layoutX="432.0" layoutY="83.0" mnemonicParsing="false" onAction="#addWord" text="add" />
<Button fx:id="delBtn" layoutX="432.0" layoutY="151.0" mnemonicParsing="false" onAction="#delWord" text="del" />
<ListView fx:id="list" layoutX="42.0" layoutY="51.0" prefHeight="275.0" prefWidth="334.0" />
</children>
<fx:root id="haha" prefHeight="253.0" prefWidth="625.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.expressionDemo.Main2">
<children>
<Label fx:id="label" layoutX="33.0" layoutY="53.0" prefHeight="37.0" prefWidth="100.0" text="账号:">
<font>
<Font size="20.0" />
</font>
</Label>
<TextField fx:id="usr" layoutX="162.0" layoutY="57.0" prefHeight="30.0" prefWidth="277.0" />
<Button fx:id="resetBtn" layoutX="33.0" layoutY="187.0" mnemonicParsing="false" onAction="#reset" text="重置" />
<Label layoutX="33.0" layoutY="116.0" prefHeight="27.0" prefWidth="69.0" text="密码">
<font>
<Font size="20.0" />
</font>
</Label>
<Button fx:id="loginBtn" layoutX="370.0" layoutY="187.0" mnemonicParsing="false" onAction="#login" text="登录" />
<Label fx:id="usrMsg" layoutX="450.0" layoutY="62.0" prefHeight="19.0" prefWidth="157.0" />
<PasswordField fx:id="psw" layoutX="162.0" layoutY="128.0" prefHeight="30.0" prefWidth="277.0" />
<Label fx:id="pswMsg" layoutX="450.0" layoutY="133.0" prefHeight="20.0" prefWidth="157.0" />
</children>
</fx:root>

View File

@@ -1,10 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import cn.edu.scau.biubiusuisui.example.actionDemo.MainController?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.Pane?>
<fx:root prefHeight="400.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.MainController">
<fx:root prefHeight="709.0" prefWidth="995.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.expressionDemo.Main2">
<children>
<Button fx:id="btn" layoutX="266.0" layoutY="179.0" mnemonicParsing="false" text="Button" />
<Button fx:id="btn" layoutX="793.0" layoutY="146.0" mnemonicParsing="false" text="Button" />
<MainController layoutX="85.0" layoutY="123.0" />
</children>
</fx:root>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.text.Font?>
<fx:root id="haha" prefHeight="253.0" prefWidth="625.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.springExpressionDemo.SpringExpressionDemoController">
<children>
<Label fx:id="label" layoutX="33.0" layoutY="53.0" prefHeight="37.0" prefWidth="100.0" text="账号:">
<font>
<Font size="20.0" />
</font>
</Label>
<TextField fx:id="usr" layoutX="162.0" layoutY="57.0" prefHeight="30.0" prefWidth="277.0" />
<Button fx:id="resetBtn" layoutX="33.0" layoutY="187.0" mnemonicParsing="false" onAction="#reset" text="重置" />
<Label layoutX="33.0" layoutY="116.0" prefHeight="27.0" prefWidth="69.0" text="密码">
<font>
<Font size="20.0" />
</font>
</Label>
<Button fx:id="loginBtn" layoutX="370.0" layoutY="187.0" mnemonicParsing="false" onAction="#login" text="登录" />
<Label fx:id="usrMsg" layoutX="450.0" layoutY="62.0" prefHeight="19.0" prefWidth="157.0" />
<PasswordField fx:id="psw" layoutX="162.0" layoutY="128.0" prefHeight="30.0" prefWidth="277.0" />
<Label fx:id="pswMsg" layoutX="450.0" layoutY="133.0" prefHeight="20.0" prefWidth="157.0" />
</children>
</fx:root>

View 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>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- <bean id="..." class="...">
collaborators and configuration for this bean go here
</bean>
<bean id="..." class="...">
collaborators and configuration for this bean go here
</bean> -->
<!-- more bean definitions go here
UserDao ud = new UserDao();
-->
<context:component-scan base-package="cn.edu.scau.biubiusuisui"/>
</beans>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.layout.Pane?>
<fx:root prefHeight="400.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.firstDemo.MainController">
<children>
<Button fx:id="addHelloButton" layoutX="432.0" layoutY="83.0" mnemonicParsing="false" onAction="#addWord"
text="add"/>
<Button fx:id="deleteHelloButton" layoutX="432.0" layoutY="151.0" mnemonicParsing="false" onAction="#delWord"
text="del"/>
<ListView fx:id="list" layoutX="42.0" layoutY="51.0" prefHeight="275.0" prefWidth="334.0"/>
</children>
</fx:root>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<?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="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>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.shape.Circle?>
<fx:root prefHeight="600.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.moveDemo.Main2">
<children>
<Circle fx:id="circle" fill="DODGERBLUE" layoutX="99.0" layoutY="191.0" radius="39.0" stroke="BLACK" strokeType="INSIDE" />
<TextField layoutX="199.0" layoutY="310.0" text="123" fx:id="xinput" />
<TextField fx:id="yinput" layoutX="199.0" layoutY="367.0" text="123" />
<Label layoutX="14.0" layoutY="315.0" text="X" />
<Label layoutX="14.0" layoutY="372.0" text="Y" />
<Button layoutX="148.0" layoutY="310.0" mnemonicParsing="false" text="-" fx:id="xSub" onAction="#subX"/>
<Button layoutX="415.0" layoutY="310.0" mnemonicParsing="false" text="+" fx:id="xAdd" onAction="#addX"/>
<Button fx:id="ySub" layoutX="148.0" layoutY="367.0" mnemonicParsing="false" text="-" onAction="#subY"/>
<Button fx:id="yAdd" layoutX="415.0" layoutY="367.0" mnemonicParsing="false" text="+" onAction="#addY"/>
</children>
</fx:root>

View 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>

View 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>

View 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>

View 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>

View File

@@ -0,0 +1,8 @@
#content {
alignment: center;
}
#content .label {
-fx-pref-height: 50;
-fx-pref-width: 100;
}

View 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>

View 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>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.Pane?>
<fx:root id="haha" prefHeight="403.0" prefWidth="625.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.springDemo.SpringController">
<children>
<Label fx:id="label" layoutX="18.0" layoutY="166.0" prefHeight="68.0" prefWidth="304.0" text="我是控制器属性" />
<Button layoutX="52.0" layoutY="98.0" onAction="#add" prefHeight="30.0" prefWidth="129.0" text="控制器1的按钮" />
</children>
</fx:root>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import cn.edu.scau.biubiusuisui.example.springDemo.SpringController?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.Pane?>
<fx:root id="haha" prefHeight="629.0" prefWidth="934.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.springDemo2.SpringController2">
<children>
<SpringController layoutX="20.0" layoutY="129.0" fx:id="springController"/>
<Button layoutX="135.0" layoutY="552.0" mnemonicParsing="false" text="Button" onAction="#test"/>
<Label layoutX="14.0" layoutY="81.0" text="Controller属性" />
<Label layoutX="20.0" layoutY="557.0" text="本控制器属性" />
<Label layoutX="385.0" layoutY="25.0" text="两个控制器之间信号传递" />
</children>
</fx:root>

View File

@@ -1,14 +1,19 @@
import cn.edu.scau.biubiusuisui.example.Student;
import cn.edu.scau.biubiusuisui.factory.FXEntityFactory;
import org.junit.Test;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
/**
* @Author jack
* @Date:2019/6/25 2:11
*/
public class MainTest {
public void testMethod(String a,int b){
}
@Test
public void test(){
public void test() throws NoSuchMethodException {
}
}

View File

@@ -0,0 +1,13 @@
package cn.edu.scau.biubiusuisui.expression;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
/**
* @Author jack
* @Date:2019/7/24 11:55
*/
public class ExpressionParserTest {
}

View File

@@ -0,0 +1,30 @@
package cn.edu.scau.biubiusuisui.expression.data;
import cn.edu.scau.biubiusuisui.annotation.FXValue;
import org.junit.Before;
import org.junit.Test;
import java.lang.reflect.Method;
import static org.junit.Assert.*;
/**
* @Author jack
* @Date:2019/7/27 3:13
*/
public class ExpressionParserTest {
private ExpressionParser expressionParser;
@Before
public void init(){
expressionParser = new ExpressionParser(null);
}
@Test
public void parse() {
}
@Test
public void getArgs() throws NoSuchMethodException {
}
}

View File

@@ -1,12 +1,7 @@
package cn.edu.scau.biubiusuisui.factory;
import cn.edu.scau.biubiusuisui.entity.FXPlusContext;
import cn.edu.scau.biubiusuisui.example.Student;
import javafx.beans.property.Property;
import org.junit.Test;
import java.util.Map;
/**
* @Author jack
* @Date:2019/6/28 1:32
@@ -34,18 +29,17 @@ public class FXEntityFactoryTest {
@Test
public void createJavaBeanProxy() {
Student student = new Student();
student.setName("NAME");
}
@Test
public void createJavaBeanProxy2() throws InstantiationException, IllegalAccessException {
Student student1 = (Student) FXEntityFactory.createJavaBeanProxy(Student.class);
System.out.println(student1);
FXPlusContext.getProryByBeanObject(student1).getStringPropertyMap().forEach((k,v)->{
System.out.println("k " +k +"v" + v);
});
student1.setName("Jack");
// Student student1 = (Student) FXEntityFactory.warpFxBean(Student.class);
// System.out.println(student1);
// FXPlusContext.getProxyByBeanObject(student1).getStringPropertyMap().forEach((k, v)->{
// System.out.println("k " +k +"v" + v);
// });
// student1.setName("Jack");
}
@Test

Some files were not shown because too many files have changed in this diff Show More