├── .gitignore ├── LICENSE ├── README.en.md ├── README.en ├── JavaFX-Plus-LifeCycle_en │ ├── JavaFX-Plus-LifeCycle_en_01.png │ └── JavaFX-Plus-LifeCycle_en_02.png ├── JavaFX-Plus.png ├── JavaFX-Plus_en.png ├── Resizable_en.gif ├── actionDemo │ └── 20191210-175409-actionDemo.gif ├── bindhow.gif ├── controllerConfig.png ├── demo1.png ├── draggable_en.gif ├── expression.gif ├── expressionV2V.gif ├── helloWorldDemo.gif ├── language_demo.gif ├── language_demo_en.gif ├── lifeDemo │ ├── lifeDemo_en.gif │ ├── lifeDemo_pkg_en.png │ ├── life_demo01_en.png │ └── life_demo_en.png ├── log_demo_en.png ├── modulesAction.gif ├── moveable.gif ├── mqDemo │ └── 20191208-194336-signalshow.gif ├── redirectDemo │ ├── 20191208-125511-not_close.gif │ └── 20191208-125739-close.gif ├── redirect_with_data_en.gif ├── resizeAble.gif ├── template_en.png ├── template_incude_en.png └── wrap_JavaBean.png ├── README.md ├── README ├── JavaFX-Plus-LifeCycle │ ├── JavaFX-Plus-LifeCycle_01.png │ └── JavaFX-Plus-LifeCycle_02.png ├── JavaFX-Plus.png ├── JavaFX-Plus_en.png ├── Resizable.gif ├── actionDemo │ └── 20191210-175409-actionDemo.gif ├── bindhow.gif ├── controllerConfig.png ├── demo1.png ├── draggable.gif ├── expression.gif ├── expressionV2V.gif ├── helloWorldDemo.gif ├── image-20200407003220469.png ├── language_demo.gif ├── lifeDemo │ ├── lifeDemo.gif │ ├── lifeDemo.png │ ├── lifeDemo_pkg.png │ └── life_demo01.png ├── log_demo.png ├── modulesAction.gif ├── moveable.gif ├── mqDemo │ └── 20191208-194336-signalshow.gif ├── redirectDemo │ ├── 20191208-125511-not_close.gif │ └── 20191208-125739-close.gif ├── redirect_with_data.gif ├── resizeAble.gif ├── template.png ├── template_incude.png └── wrap_JavaBean.png ├── doc ├── JavaFX-Plus-Introduction.xmind ├── JavaFX-Plus-Introduction_en.xmind ├── JavaFX-Plus-LifeCycle.pptx └── JavaFX-Plus-LifeCycle_en.pptx ├── pom.xml └── src ├── main ├── java │ └── cn │ │ └── edu │ │ └── scau │ │ └── biubiusuisui │ │ ├── annotation │ │ ├── FXBind.java │ │ ├── FXController.java │ │ ├── FXData.java │ │ ├── FXEntity.java │ │ ├── FXField.java │ │ ├── FXReceiver.java │ │ ├── FXRedirect.java │ │ ├── FXScan.java │ │ ├── FXSender.java │ │ ├── FXValue.java │ │ └── FXWindow.java │ │ ├── config │ │ ├── FXMLLoaderPlus.java │ │ └── FXPlusApplication.java │ │ ├── entity │ │ ├── FXBaseController.java │ │ ├── FXFieldWrapper.java │ │ ├── FXMethodEntity.java │ │ ├── FXPlusContext.java │ │ ├── FXPlusLocale.java │ │ └── FXRedirectParam.java │ │ ├── example │ │ ├── bindDemo │ │ │ ├── BindDemo.java │ │ │ ├── MainController.java │ │ │ ├── Profile.java │ │ │ ├── User.java │ │ │ └── UserPropertyEntity.java │ │ ├── firstDemo │ │ │ ├── FirstDemo.java │ │ │ ├── MainController.java │ │ │ └── Student.java │ │ ├── languageDemo │ │ │ ├── ChineseController.java │ │ │ ├── EnglishController.java │ │ │ ├── KoreanController.java │ │ │ └── LanguageDemo.java │ │ ├── lifeDemo │ │ │ ├── DialogController.java │ │ │ ├── LifeDemo.java │ │ │ ├── MainController.java │ │ │ └── SubController.java │ │ ├── listDemo │ │ │ ├── ListDemo.java │ │ │ ├── MainController.java │ │ │ └── User.java │ │ ├── logDemo │ │ │ └── LogDemo.java │ │ ├── mqDemo │ │ │ ├── MQDemo.java │ │ │ ├── MainController.java │ │ │ └── TopBarController.java │ │ ├── redirectDemo │ │ │ ├── DialogController.java │ │ │ ├── LoginController.java │ │ │ ├── RedirectDemo.java │ │ │ ├── RegisterController.java │ │ │ ├── SuccessController.java │ │ │ └── UserEntity.java │ │ └── resizableDemo │ │ │ ├── MainController.java │ │ │ └── ResizableDemo.java │ │ ├── exception │ │ ├── InvalidURLException.java │ │ ├── NoSuchChangeMethod.java │ │ ├── NotFXWindowException.java │ │ └── ProtocolNotSupport.java │ │ ├── expression │ │ ├── BindParser.java │ │ ├── action │ │ │ └── ChangeParser.java │ │ └── data │ │ │ ├── ExpFunction.java │ │ │ ├── ExpressionParser.java │ │ │ ├── FunctionExpression.java │ │ │ ├── MyBeanAdapter.java │ │ │ └── MyExpressionValue.java │ │ ├── factory │ │ ├── BeanBuilder.java │ │ ├── FXBuilder.java │ │ ├── FXControllerFactory.java │ │ └── FXEntityFactory.java │ │ ├── function │ │ ├── DragWindowHandlerImpl.java │ │ ├── Draggale.java │ │ └── FXWindowParser.java │ │ ├── log │ │ ├── FXPlusLogger.java │ │ ├── FXPlusLoggerContext.java │ │ ├── FXPlusLoggerFactory.java │ │ └── IFXPlusLogger.java │ │ ├── messageQueue │ │ └── MessageQueue.java │ │ ├── proxy │ │ ├── FXControllerProxy.java │ │ └── FXEntityProxy.java │ │ ├── stage │ │ └── StageManager.java │ │ └── utils │ │ ├── BeanUtil.java │ │ ├── ClassUtil.java │ │ ├── FileUtil.java │ │ ├── LogUtil.java │ │ ├── PathUtil.java │ │ ├── ResourceBundleUtil.java │ │ └── StringUtil.java └── resources │ ├── applicationContext.xml │ ├── banner.txt │ ├── fxml │ ├── Main.fxml │ ├── Main2.fxml │ ├── SpringExpressionDemo.fxml │ ├── bindDemo │ │ └── bindDemo.fxml │ ├── firstDemo │ │ └── firstDemo.fxml │ ├── index.js │ ├── languageDemo │ │ ├── languageDemo.fxml │ │ ├── languageDemo_en.properties │ │ ├── languageDemo_ko.properties │ │ └── languageDemo_zh_CN.properties │ ├── lifeDemo │ │ ├── dialog.fxml │ │ ├── dialog_en.properties │ │ ├── dialog_zh_CN.properties │ │ ├── lifeMain.fxml │ │ ├── lifeMain_en.properties │ │ ├── lifeMain_zh_CN.properties │ │ ├── subBar.fxml │ │ ├── subBar_en.properties │ │ └── subBar_zh_CN.properties │ ├── listDemo │ │ └── listDemo.fxml │ ├── moveDemo.fxml │ ├── mqDemo │ │ ├── main.fxml │ │ └── topBar.fxml │ ├── redirectDemo │ │ ├── dialog.fxml │ │ ├── login.fxml │ │ ├── register.css │ │ ├── register.fxml │ │ └── success.fxml │ ├── resizableDemo │ │ └── resizableDemo.fxml │ ├── springDemo.fxml │ └── springDemo2.fxml │ ├── image │ └── icon.png │ ├── language │ ├── javafxplus_en.properties │ └── javafxplus_zh_CN.properties │ └── log4j.properties └── test └── java ├── MainTest.java └── cn └── edu └── scau └── biubiusuisui ├── expression ├── ExpressionParserTest.java └── data │ └── ExpressionParserTest.java ├── factory └── FXEntityFactoryTest.java └── utils └── ClassUtilsTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Biubiu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.en/JavaFX-Plus-LifeCycle_en/JavaFX-Plus-LifeCycle_en_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/JavaFX-Plus-LifeCycle_en/JavaFX-Plus-LifeCycle_en_01.png -------------------------------------------------------------------------------- /README.en/JavaFX-Plus-LifeCycle_en/JavaFX-Plus-LifeCycle_en_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/JavaFX-Plus-LifeCycle_en/JavaFX-Plus-LifeCycle_en_02.png -------------------------------------------------------------------------------- /README.en/JavaFX-Plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/JavaFX-Plus.png -------------------------------------------------------------------------------- /README.en/JavaFX-Plus_en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/JavaFX-Plus_en.png -------------------------------------------------------------------------------- /README.en/Resizable_en.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/Resizable_en.gif -------------------------------------------------------------------------------- /README.en/actionDemo/20191210-175409-actionDemo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/actionDemo/20191210-175409-actionDemo.gif -------------------------------------------------------------------------------- /README.en/bindhow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/bindhow.gif -------------------------------------------------------------------------------- /README.en/controllerConfig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/controllerConfig.png -------------------------------------------------------------------------------- /README.en/demo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/demo1.png -------------------------------------------------------------------------------- /README.en/draggable_en.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/draggable_en.gif -------------------------------------------------------------------------------- /README.en/expression.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/expression.gif -------------------------------------------------------------------------------- /README.en/expressionV2V.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/expressionV2V.gif -------------------------------------------------------------------------------- /README.en/helloWorldDemo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/helloWorldDemo.gif -------------------------------------------------------------------------------- /README.en/language_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/language_demo.gif -------------------------------------------------------------------------------- /README.en/language_demo_en.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/language_demo_en.gif -------------------------------------------------------------------------------- /README.en/lifeDemo/lifeDemo_en.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/lifeDemo/lifeDemo_en.gif -------------------------------------------------------------------------------- /README.en/lifeDemo/lifeDemo_pkg_en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/lifeDemo/lifeDemo_pkg_en.png -------------------------------------------------------------------------------- /README.en/lifeDemo/life_demo01_en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/lifeDemo/life_demo01_en.png -------------------------------------------------------------------------------- /README.en/lifeDemo/life_demo_en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/lifeDemo/life_demo_en.png -------------------------------------------------------------------------------- /README.en/log_demo_en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/log_demo_en.png -------------------------------------------------------------------------------- /README.en/modulesAction.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/modulesAction.gif -------------------------------------------------------------------------------- /README.en/moveable.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/moveable.gif -------------------------------------------------------------------------------- /README.en/mqDemo/20191208-194336-signalshow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/mqDemo/20191208-194336-signalshow.gif -------------------------------------------------------------------------------- /README.en/redirectDemo/20191208-125511-not_close.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/redirectDemo/20191208-125511-not_close.gif -------------------------------------------------------------------------------- /README.en/redirectDemo/20191208-125739-close.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/redirectDemo/20191208-125739-close.gif -------------------------------------------------------------------------------- /README.en/redirect_with_data_en.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/redirect_with_data_en.gif -------------------------------------------------------------------------------- /README.en/resizeAble.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/resizeAble.gif -------------------------------------------------------------------------------- /README.en/template_en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/template_en.png -------------------------------------------------------------------------------- /README.en/template_incude_en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/template_incude_en.png -------------------------------------------------------------------------------- /README.en/wrap_JavaBean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README.en/wrap_JavaBean.png -------------------------------------------------------------------------------- /README/JavaFX-Plus-LifeCycle/JavaFX-Plus-LifeCycle_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/JavaFX-Plus-LifeCycle/JavaFX-Plus-LifeCycle_01.png -------------------------------------------------------------------------------- /README/JavaFX-Plus-LifeCycle/JavaFX-Plus-LifeCycle_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/JavaFX-Plus-LifeCycle/JavaFX-Plus-LifeCycle_02.png -------------------------------------------------------------------------------- /README/JavaFX-Plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/JavaFX-Plus.png -------------------------------------------------------------------------------- /README/JavaFX-Plus_en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/JavaFX-Plus_en.png -------------------------------------------------------------------------------- /README/Resizable.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/Resizable.gif -------------------------------------------------------------------------------- /README/actionDemo/20191210-175409-actionDemo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/actionDemo/20191210-175409-actionDemo.gif -------------------------------------------------------------------------------- /README/bindhow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/bindhow.gif -------------------------------------------------------------------------------- /README/controllerConfig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/controllerConfig.png -------------------------------------------------------------------------------- /README/demo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/demo1.png -------------------------------------------------------------------------------- /README/draggable.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/draggable.gif -------------------------------------------------------------------------------- /README/expression.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/expression.gif -------------------------------------------------------------------------------- /README/expressionV2V.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/expressionV2V.gif -------------------------------------------------------------------------------- /README/helloWorldDemo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/helloWorldDemo.gif -------------------------------------------------------------------------------- /README/image-20200407003220469.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/image-20200407003220469.png -------------------------------------------------------------------------------- /README/language_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/language_demo.gif -------------------------------------------------------------------------------- /README/lifeDemo/lifeDemo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/lifeDemo/lifeDemo.gif -------------------------------------------------------------------------------- /README/lifeDemo/lifeDemo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/lifeDemo/lifeDemo.png -------------------------------------------------------------------------------- /README/lifeDemo/lifeDemo_pkg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/lifeDemo/lifeDemo_pkg.png -------------------------------------------------------------------------------- /README/lifeDemo/life_demo01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/lifeDemo/life_demo01.png -------------------------------------------------------------------------------- /README/log_demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/log_demo.png -------------------------------------------------------------------------------- /README/modulesAction.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/modulesAction.gif -------------------------------------------------------------------------------- /README/moveable.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/moveable.gif -------------------------------------------------------------------------------- /README/mqDemo/20191208-194336-signalshow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/mqDemo/20191208-194336-signalshow.gif -------------------------------------------------------------------------------- /README/redirectDemo/20191208-125511-not_close.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/redirectDemo/20191208-125511-not_close.gif -------------------------------------------------------------------------------- /README/redirectDemo/20191208-125739-close.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/redirectDemo/20191208-125739-close.gif -------------------------------------------------------------------------------- /README/redirect_with_data.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/redirect_with_data.gif -------------------------------------------------------------------------------- /README/resizeAble.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/resizeAble.gif -------------------------------------------------------------------------------- /README/template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/template.png -------------------------------------------------------------------------------- /README/template_incude.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/template_incude.png -------------------------------------------------------------------------------- /README/wrap_JavaBean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/README/wrap_JavaBean.png -------------------------------------------------------------------------------- /doc/JavaFX-Plus-Introduction.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/doc/JavaFX-Plus-Introduction.xmind -------------------------------------------------------------------------------- /doc/JavaFX-Plus-Introduction_en.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/doc/JavaFX-Plus-Introduction_en.xmind -------------------------------------------------------------------------------- /doc/JavaFX-Plus-LifeCycle.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/doc/JavaFX-Plus-LifeCycle.pptx -------------------------------------------------------------------------------- /doc/JavaFX-Plus-LifeCycle_en.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillKiller/JavaFX-Plus/ffc17362bde93677793c529b6bb557a3dae3819a/doc/JavaFX-Plus-LifeCycle_en.pptx -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | javafx-plus 7 | 8 | com.gitee.Biubiuyuyu 9 | javafx-plus 10 | 1.2.0-RELEASE 11 | pom 12 | 13 | 14 | 15 | org.sonatype.oss 16 | oss-parent 17 | 7 18 | 19 | 20 | this is javafx framework that simplified coding 21 | 22 | 23 | 24 | javafx-plus 25 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 26 | 27 | 28 | javafx-plus 29 | https://oss.sonatype.org/content/repositories/snapshots 30 | 31 | 32 | 33 | 34 | 35 | 36 | cglib 37 | cglib 38 | 3.1 39 | 40 | 41 | 42 | junit 43 | junit 44 | 4.11 45 | test 46 | 47 | 48 | 49 | 50 | org.slf4j 51 | slf4j-log4j12 52 | 1.7.21 53 | 54 | 55 | org.apache.tomcat.embed 56 | tomcat-embed-core 57 | 9.0.35 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | org.apache.maven.plugins 66 | maven-compiler-plugin 67 | 68 | 1.8 69 | 1.8 70 | 71 | 72 | -Xlint:deprecation 73 | 74 | 75 | 76 | 77 | 79 | ${java.home}/lib/rt.jar:${java.home}/lib/jce.jar 80 | 81 | 82 | 83 | 84 | maven-assembly-plugin 85 | 86 | 87 | jar-with-dependencies 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | release 97 | 98 | 99 | 100 | 101 | org.apache.maven.plugins 102 | maven-source-plugin 103 | 2.2.1 104 | 105 | 106 | package 107 | 108 | jar-no-fork 109 | 110 | 111 | 112 | 113 | 114 | 115 | org.apache.maven.plugins 116 | maven-javadoc-plugin 117 | 2.9.1 118 | 119 | 120 | package 121 | 122 | jar 123 | 124 | 125 | -Xdoclint:none 126 | 127 | 128 | 129 | 130 | 131 | 132 | org.apache.maven.plugins 133 | maven-gpg-plugin 134 | 1.5 135 | 136 | 137 | sign-artifacts 138 | verify 139 | 140 | sign 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | GNU Lesser General Public License Version 3 153 | http://www.gnu.org/licenses/lgpl.txt 154 | repo 155 | 156 | 157 | 158 | master 159 | https://gitee.com/Biubiuyuyu/JavaFX-Plus.git 160 | scm:git:https://gitee.com/Biubiuyuyu/JavaFX-Plus.git 161 | scm:git:https://gitee.com/Biubiuyuyu/JavaFX-Plus.git 162 | 163 | 164 | 165 | Zhu zhanbiao 166 | 747441355@qq.com 167 | cn.edu.scau 168 | 169 | 170 | 171 | Yang suiyu 172 | 498870048@qq.com 173 | cn.edu.scau 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/annotation/FXBind.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @version 1.0 7 | * @since JavaFX2.0 JDK1.8 8 | */ 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Target(ElementType.FIELD) 11 | @Inherited 12 | public @interface FXBind { 13 | String[] value(); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/annotation/FXController.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.annotation; 2 | 3 | import cn.edu.scau.biubiusuisui.entity.FXPlusLocale; 4 | 5 | import java.lang.annotation.*; 6 | 7 | /** 8 | * This is use for marking A controller as FX-Plus Controller 9 | * 10 | * @author jack 11 | * @author suisui 12 | * @version 1.0 13 | * @date 2019/6/25 1:34 14 | * @since JavaFX2.0 JDK1.8 15 | */ 16 | @Retention(RetentionPolicy.RUNTIME) 17 | @Target(ElementType.TYPE) 18 | @Inherited 19 | public @interface FXController { 20 | String path(); 21 | 22 | double preWidth() default 0.0; 23 | 24 | double preHeight() default 0.0; 25 | 26 | /** 27 | * @return 28 | * @description 程序语言,默认不设置 29 | * @version 1.2 30 | */ 31 | FXPlusLocale locale() default FXPlusLocale.NONE; 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/annotation/FXData.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author jack 7 | * @version 1.0 8 | * @date 2019/6/25 1:36 9 | * @since JavaFX2.0 JDK1.8 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target(ElementType.FIELD) 13 | @Inherited 14 | public @interface FXData { 15 | String fx_id() default ""; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/annotation/FXEntity.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author jack 7 | * @version 1.0 8 | * @date 2019/6/25 1:35 9 | * @since JavaFX2.0 JDK1.8 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target(ElementType.TYPE) 13 | @Inherited 14 | public @interface FXEntity { 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/annotation/FXField.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author jack 10 | * @version 1.0 11 | * @date 2019/6/27 20:10 12 | * @since JavaFX2.0 JDK1.8 13 | */ 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Target(ElementType.FIELD) 16 | public @interface FXField { 17 | boolean readOnly() default false; 18 | 19 | String setter() default ""; 20 | 21 | String add() default ""; 22 | 23 | String delete() default ""; 24 | 25 | String edit() default ""; 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/annotation/FXReceiver.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author jack 7 | * @version 1.0 8 | * @date 2019/6/25 13:06 9 | * @since JavaFX2.0 JDK1.8 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Inherited 13 | @Target(ElementType.METHOD) 14 | public @interface FXReceiver { 15 | String name(); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/annotation/FXRedirect.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author suisui 7 | * @version 1.1 8 | * @description 重定向的注解 9 | * @date 2019/12/3 12:53 10 | * @since JavaFX2.0 JDK1.8 11 | */ 12 | 13 | @Retention(RetentionPolicy.RUNTIME) 14 | @Target(ElementType.METHOD) 15 | @Inherited 16 | public @interface FXRedirect { 17 | boolean close() default true; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/annotation/FXScan.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author jack 10 | * @date 2019/6/25 2:55 11 | * @since JavaFX2.0 JDK1.8 12 | */ 13 | @Retention(RetentionPolicy.RUNTIME) 14 | @Target(ElementType.TYPE) 15 | public @interface FXScan { 16 | String[] base() default "."; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/annotation/FXSender.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * This cn.edu.scau.biubiusuisui.annotation is used for a method which can send a signal to all consumer 10 | * And FXSender has a name which is used for identifying different method 11 | * It is legal to use same method which has same name because JavaFX-Plus will identify a method with its full class name 12 | * In addition ,name is optional , default name will be the class name and method name 13 | * you can use this cn.edu.scau.biubiusuisui.annotation as the following cn.edu.scau.biubiusuisui.example 14 | *

15 | * \@FXSender 16 | * public class A{ 17 | * public void test(){ 18 | *

19 | * } 20 | * } 21 | * name will be A.name(It will only contain base class name and this name) 22 | * or you can use 23 | * 24 | * @author jack 25 | * @version 1.0 26 | * @FXSernder("testDemo") public class A{ 27 | * public void test(){ 28 | *

29 | * } 30 | * } 31 | * name will be A.testDemo 32 | * @date 2019/6/25 13:02 33 | * @since JavaFX2.0 JDK1.8 34 | */ 35 | @Retention(RetentionPolicy.RUNTIME) 36 | @Target(ElementType.METHOD) 37 | public @interface FXSender { 38 | String name() default ""; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/annotation/FXValue.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author jack 7 | * @version 1.0 8 | * @date 2019/7/27 3:06 9 | * @since JavaFX2.0 JDK1.8 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target(ElementType.PARAMETER) 13 | @Inherited 14 | public @interface FXValue { 15 | String value(); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/annotation/FXWindow.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.annotation; 2 | 3 | import cn.edu.scau.biubiusuisui.entity.FXPlusLocale; 4 | import javafx.stage.StageStyle; 5 | 6 | import java.lang.annotation.*; 7 | import java.util.Locale; 8 | 9 | /** 10 | * @author jack 11 | * @author suisui 12 | * @version 1.0 13 | * @date 2019/6/25 1:36 14 | * @since JavaFX2.0 JDK1.8 15 | */ 16 | @Retention(RetentionPolicy.RUNTIME) 17 | @Target(ElementType.TYPE) 18 | @Inherited 19 | public @interface FXWindow { 20 | double preWidth() default 0.0; 21 | 22 | double preHeight() default 0.0; 23 | 24 | double minWidth() default 0.0; 25 | 26 | double minHeight() default 0.0; 27 | 28 | boolean resizable() default false; 29 | 30 | boolean draggable() default false; 31 | 32 | boolean mainStage() default false; 33 | 34 | StageStyle style() default StageStyle.DECORATED; 35 | 36 | String title(); 37 | 38 | /** 39 | * @description 图标URL 40 | * @version 1.2 41 | */ 42 | String icon() default ""; 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/config/FXPlusApplication.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.config; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXScan; 4 | import cn.edu.scau.biubiusuisui.annotation.FXWindow; 5 | import cn.edu.scau.biubiusuisui.factory.BeanBuilder; 6 | import cn.edu.scau.biubiusuisui.factory.FXBuilder; 7 | import cn.edu.scau.biubiusuisui.factory.FXControllerFactory; 8 | import cn.edu.scau.biubiusuisui.function.FXWindowParser; 9 | import cn.edu.scau.biubiusuisui.log.FXPlusLoggerFactory; 10 | import cn.edu.scau.biubiusuisui.log.IFXPlusLogger; 11 | import cn.edu.scau.biubiusuisui.utils.ClassUtil; 12 | import cn.edu.scau.biubiusuisui.utils.FileUtil; 13 | import cn.edu.scau.biubiusuisui.utils.LogUtil; 14 | 15 | import java.lang.annotation.Annotation; 16 | import java.util.HashSet; 17 | import java.util.List; 18 | import java.util.Set; 19 | 20 | /** 21 | * @author jack 22 | * @version 1.0 23 | * @date 2019/6/25 2:54 24 | * @since JavaFX2.0 JDK1.8 25 | */ 26 | public class FXPlusApplication { 27 | private static final IFXPlusLogger logger = FXPlusLoggerFactory.getLogger(FXPlusApplication.class); 28 | // Application 29 | 30 | private static FXWindowParser windowAnnotationParser = new FXWindowParser(); 31 | 32 | private static BeanBuilder DEFAULT_BEAN_FACTORY = new FXBuilder(); 33 | 34 | private static BeanBuilder beanBuilder; 35 | 36 | public static boolean IS_SCENE_BUILDER = true; 37 | 38 | public static void start(Class clazz, BeanBuilder beanBuilder) { 39 | logger.info("starting JavaFX-Plus Application"); 40 | logger.info("\n" + FileUtil.readFileFromResources("banner.txt")); 41 | // 初始化日志路径 42 | LogUtil.initLog4jBase(); 43 | 44 | IS_SCENE_BUILDER = false; 45 | FXPlusApplication.beanBuilder = beanBuilder; 46 | Annotation[] annotations = clazz.getDeclaredAnnotations(); 47 | logger.info("starting to scanning and registering controllers"); 48 | for (Annotation annotation : annotations) { 49 | if (FXScan.class.equals(annotation.annotationType())) { 50 | String[] dirs = ((FXScan) annotation).base(); 51 | Set sets = new HashSet<>(); 52 | for (String dir : dirs) { 53 | sets.add(dir); 54 | } 55 | Set classNames = new HashSet<>(); 56 | for (String dir : sets) { 57 | logger.info("scanning directory: " + dir); 58 | ClassUtil classUtil = new ClassUtil(); 59 | List temps = classUtil.scanAllClassName(dir); 60 | for (String className : temps) { 61 | try { 62 | logger.info("loading class: " + className); 63 | loadFXPlusClass(className, beanBuilder); 64 | } catch (ClassNotFoundException e) { 65 | logger.error(e.getMessage()); 66 | e.printStackTrace(); 67 | } 68 | } 69 | } 70 | } 71 | } 72 | } 73 | 74 | public static void start(Class clazz) { 75 | start(clazz, DEFAULT_BEAN_FACTORY); 76 | } 77 | 78 | private static void loadFXPlusClass(String className, BeanBuilder beanBuilder) throws ClassNotFoundException { 79 | Class clazz = Class.forName(className); 80 | // 是窗口,需要初始化Stage 81 | if (clazz.getAnnotation(FXWindow.class) != null) { 82 | logger.info("loading stage of class: " + className); 83 | FXControllerFactory.loadStage(clazz, beanBuilder); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/entity/FXFieldWrapper.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.entity; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXField; 4 | import javafx.beans.property.Property; 5 | 6 | /** 7 | * 将Controller中的JavaFX的field包装成FXFieldWrapper 8 | * 9 | * @author jack 10 | * @version 1.0 11 | * @date 2019/6/28 10:03 12 | * @since JavaFX2.0 JDK1.8 13 | */ 14 | public class FXFieldWrapper { 15 | 16 | private FXField fxField; 17 | private Class type; 18 | 19 | private Property property; 20 | 21 | public FXFieldWrapper() { 22 | } 23 | 24 | public FXFieldWrapper(FXField fxField, Class type) { 25 | this.fxField = fxField; 26 | this.type = type; 27 | } 28 | 29 | public Class getType() { 30 | return type; 31 | } 32 | 33 | public void setType(Class type) { 34 | this.type = type; 35 | } 36 | 37 | public FXField getFxField() { 38 | return fxField; 39 | } 40 | 41 | public void setFxField(FXField fxField) { 42 | this.fxField = fxField; 43 | } 44 | 45 | public Property getProperty() { 46 | return property; 47 | } 48 | 49 | public void setProperty(Property property) { 50 | this.property = property; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/entity/FXMethodEntity.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.entity; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | /** 6 | * This class is base cn.edu.scau.biubiusuisui.entity for queue message(or signal) 7 | * you mush save the instance and method which means who will run this method 8 | * 9 | * @author jack 10 | * @version 1.0 11 | * @date 2019/6/26 15:39 12 | * @since JavaFX2.0 JDK1.8 13 | */ 14 | public class FXMethodEntity { 15 | 16 | private FXBaseController fxBaseController; 17 | 18 | private Method method; 19 | 20 | public FXMethodEntity(FXBaseController fxBaseController, Method method) { 21 | this.fxBaseController = fxBaseController; 22 | this.method = method; 23 | } 24 | 25 | public FXBaseController getFxBaseController() { 26 | return fxBaseController; 27 | } 28 | 29 | public void setFxBaseController(FXBaseController fxBaseController) { 30 | this.fxBaseController = fxBaseController; 31 | } 32 | 33 | public Method getMethod() { 34 | return method; 35 | } 36 | 37 | public void setMethod(Method method) { 38 | this.method = method; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/entity/FXPlusContext.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.entity; 2 | 3 | import cn.edu.scau.biubiusuisui.proxy.FXEntityProxy; 4 | import javafx.beans.property.Property; 5 | 6 | import java.util.LinkedList; 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.concurrent.ConcurrentHashMap; 10 | 11 | /** 12 | * Context is use for storing Controller 13 | * In addition,you can store an instance into Session to use it everywhere 14 | * 15 | * @author jack 16 | * @version 1.0 17 | * @date 2019/6/26 12:28 18 | * @since JavaFX2.0 JDK1.8 19 | */ 20 | public class FXPlusContext { 21 | 22 | private FXPlusContext() { 23 | } 24 | 25 | private static Map> controllerContext = new ConcurrentHashMap<>(); //FXController控制器注册表 26 | 27 | private static Map beanMap = new ConcurrentHashMap<>(); // Object注册为FXEntityObject 28 | 29 | 30 | public static void registerController(FXBaseController fxBaseController) { 31 | List controllers = controllerContext.get(fxBaseController.getName()); 32 | if (controllers == null) { 33 | controllers = new LinkedList<>(); 34 | } 35 | controllers.add(fxBaseController); 36 | } 37 | 38 | 39 | public static FXEntityProxy getProxyByBeanObject(Object object) { 40 | return beanMap.get(object); 41 | } 42 | 43 | public static void setProxyByBeanObject(Object object, FXEntityProxy fxEntityProxy) { 44 | beanMap.put(object, fxEntityProxy); 45 | } 46 | 47 | public static List getControllers(String key) { 48 | return controllerContext.get(key); 49 | } 50 | 51 | public static Property getEntityPropertyByName(Object object, String fieldName) { 52 | return getProxyByBeanObject(object).getPropertyByFieldName(fieldName); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/entity/FXPlusLocale.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.entity; 2 | 3 | /** 4 | * @author suisui 5 | * @version 1.2 6 | * @description JavaFX的Locale枚举类型 7 | * @date 2020/5/3 10:47 8 | * @since JDK1.8 JavaFX2.0 9 | */ 10 | public enum FXPlusLocale { 11 | /** 12 | * 不设置 13 | */ 14 | NONE, 15 | 16 | /** 17 | * 简体中文 18 | */ 19 | SIMPLIFIED_CHINESE, 20 | 21 | /** 22 | * 繁体中文 23 | */ 24 | TRADITIONAL_CHINESE, 25 | 26 | 27 | /** 28 | * English 英语 29 | */ 30 | ENGLISH, 31 | 32 | 33 | /** 34 | * American 美语 35 | */ 36 | AMERICAN, 37 | 38 | 39 | /** 40 | * Le français 法语 41 | */ 42 | FRANCE, 43 | 44 | 45 | /** 46 | * Deutsch 德语 47 | */ 48 | GERMANY, 49 | 50 | 51 | /** 52 | * lingua italiana 意大利语 53 | */ 54 | ITALIAN, 55 | 56 | 57 | /** 58 | * 日本人 日语 59 | */ 60 | JAPANESE, 61 | 62 | 63 | /** 64 | * 한국어 韩语 65 | */ 66 | KOREAN, 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/entity/FXRedirectParam.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.entity; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @author suisui 8 | * @version 1.2 9 | * @description 跳转窗口携带的参数 10 | * @date 2020/4/6 18:06 11 | * @since JavaFX2.0 JDK1.8 12 | */ 13 | public class FXRedirectParam { 14 | private String toController; 15 | private Map query = new HashMap<>(); 16 | private Map params = new HashMap<>(); 17 | 18 | public FXRedirectParam(String toController) { 19 | this.toController = toController; 20 | } 21 | 22 | public String getToController() { 23 | return toController; 24 | } 25 | 26 | public void setToController(String toController) { 27 | this.toController = toController; 28 | } 29 | 30 | public Map getParams() { 31 | return params; 32 | } 33 | 34 | public Map getQueryMap() { 35 | return query; 36 | } 37 | 38 | 39 | public void addParam(String key, Object param) { 40 | this.params.put(key, param); 41 | } 42 | 43 | public Object getParam(String key) { 44 | return this.params.get(key); 45 | } 46 | 47 | public void addQuery(String key, Object param) { 48 | this.query.put(key, param); 49 | } 50 | 51 | public Object getOneQuery(String key) { 52 | return this.query.get(key); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/bindDemo/BindDemo.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.bindDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXScan; 4 | import cn.edu.scau.biubiusuisui.config.FXPlusApplication; 5 | import javafx.application.Application; 6 | import javafx.stage.Stage; 7 | 8 | /** 9 | * @author jack 10 | * @author suisui 11 | * @version 1.2 12 | * @date 2020/5/1 1:43 13 | * @since JavaFX2.0 JDK1.8 14 | */ 15 | @FXScan(base = "cn.edu.scau.biubiusuisui.example.bindDemo") 16 | public class BindDemo extends Application { 17 | @Override 18 | public void start(Stage primaryStage) throws Exception { 19 | FXPlusApplication.start(BindDemo.class); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/bindDemo/MainController.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.bindDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXBind; 4 | import cn.edu.scau.biubiusuisui.annotation.FXController; 5 | import cn.edu.scau.biubiusuisui.annotation.FXWindow; 6 | import cn.edu.scau.biubiusuisui.entity.FXBaseController; 7 | import javafx.beans.value.ChangeListener; 8 | import javafx.beans.value.ObservableValue; 9 | import javafx.fxml.FXML; 10 | import javafx.fxml.Initializable; 11 | import javafx.scene.control.*; 12 | 13 | import java.net.URL; 14 | import java.util.ResourceBundle; 15 | 16 | /** 17 | * @author jack 18 | * @author suisui 19 | * @version 1.2 20 | * @date 2020/5/1 1:43 21 | * @since JavaFX2.0 JDK1.8 22 | */ 23 | @FXController(path = "fxml/bindDemo/bindDemo.fxml") 24 | @FXWindow(title = "bindDemo", mainStage = true) 25 | // TODO 待完善 26 | public class MainController extends FXBaseController implements Initializable { 27 | // View bind to View 28 | @FXML 29 | @FXBind("text=${inputTF.text}") 30 | private Label inputLabel; 31 | 32 | @FXML 33 | private TextField inputTF; 34 | 35 | // View bind to a Java Bean 36 | @FXML 37 | private Label usernameLabel; 38 | 39 | @FXML 40 | private Label userPswLabel; 41 | 42 | @FXML 43 | private Label ageLabel; 44 | 45 | @FXML 46 | private Label enableLabel; 47 | 48 | @FXML 49 | private TextField usernameTF; 50 | 51 | @FXML 52 | private PasswordField pswPF; 53 | 54 | @FXML 55 | private TextField ageTF; 56 | 57 | @FXML 58 | private ToggleGroup enableButtons; 59 | 60 | // 61 | // @FXData 62 | // @FXBind({ 63 | // "name=${usernameTF.text}", 64 | // "password=${pswPF.text}", 65 | // "age=${ageTF.text}", 66 | // "isEnable=${enableButtons.getSelectedToggle().getUserData()}" 67 | // }) 68 | // private User user = new User(); 69 | private UserPropertyEntity user = new UserPropertyEntity(); 70 | 71 | // View bind to Expression 72 | @FXML 73 | private TextField money; 74 | 75 | @FXML 76 | @FXBind("text=${@toUs(money.text)}") 77 | private Label us; 78 | 79 | @FXML 80 | @FXBind("text=${@toJp(money.text)}") 81 | private Label jp; 82 | 83 | @FXML 84 | @FXBind("text=${@toUk(money.text)}") 85 | private Label uk; 86 | 87 | @Override 88 | public void initialize(URL location, ResourceBundle resources) { 89 | money.setText("0"); 90 | money.textProperty().addListener(new ChangeListener() { 91 | @Override 92 | public void changed(ObservableValue observable, String oldValue, String newValue) { 93 | if (null == newValue || "".equals(newValue)) { 94 | money.setText("0"); 95 | } else if (!newValue.matches("^[0-9]*$")) { 96 | money.setText(oldValue); 97 | } 98 | } 99 | }); 100 | } 101 | 102 | @FXML 103 | public void clickToShowInfo() { 104 | RadioButton button = (RadioButton) enableButtons.getSelectedToggle(); 105 | System.out.println(button.getText()); 106 | usernameLabel.setText(user.getName()); 107 | userPswLabel.setText(user.getPassword()); 108 | ageLabel.setText(Integer.toString(user.getAge())); 109 | enableLabel.setText(Boolean.toString(user.getEnable())); 110 | } 111 | 112 | public String toUs(String value) { 113 | double money = Double.valueOf(value); 114 | double percent = 0.1454; 115 | return String.valueOf(money * percent); 116 | } 117 | 118 | public String toJp(String value) { 119 | double money = Double.valueOf(value); 120 | double percent = 15.797; 121 | return String.valueOf(money * percent); 122 | } 123 | 124 | public String toUk(String value) { 125 | double money = Double.valueOf(value); 126 | double percent = 0.1174; 127 | return String.valueOf(money * percent); 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/bindDemo/Profile.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.bindDemo; 2 | 3 | /** 4 | * @author suisui 5 | * @version 1.2 6 | * @description 详细信息 7 | * @date 2020/4/6 00:29 8 | * @since JavaFX2.0 JDK1.8 9 | */ 10 | public class Profile { 11 | private String birthday; 12 | private String address; 13 | private String avatar; 14 | 15 | public String getBirthday() { 16 | return birthday; 17 | } 18 | 19 | public void setBirthday(String birthday) { 20 | this.birthday = birthday; 21 | } 22 | 23 | public String getAddress() { 24 | return address; 25 | } 26 | 27 | public void setAddress(String address) { 28 | this.address = address; 29 | } 30 | 31 | public String getAvatar() { 32 | return avatar; 33 | } 34 | 35 | public void setAvatar(String avatar) { 36 | this.avatar = avatar; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/bindDemo/User.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.bindDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXEntity; 4 | import cn.edu.scau.biubiusuisui.annotation.FXField; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author suisui 10 | * @version 1.2 11 | * @date 2020/4/5 12:19 12 | * @since JavaFX2.0 JDK1.8 13 | */ 14 | @FXEntity 15 | public class User { 16 | @FXField 17 | private String name; 18 | @FXField 19 | private String password; 20 | @FXField 21 | private Integer age; 22 | @FXField 23 | private List scores; 24 | @FXField 25 | private Double gpa;//平均分 26 | @FXField 27 | private Profile profile; 28 | @FXField 29 | private boolean isEnable; 30 | 31 | public String getName() { 32 | return name; 33 | } 34 | 35 | public void setName(String name) { 36 | this.name = name; 37 | } 38 | 39 | public String getPassword() { 40 | return password; 41 | } 42 | 43 | public void setPassword(String password) { 44 | this.password = password; 45 | } 46 | 47 | public Integer getAge() { 48 | return age; 49 | } 50 | 51 | public void setAge(Integer age) { 52 | this.age = age; 53 | } 54 | 55 | public List getScores() { 56 | return scores; 57 | } 58 | 59 | public void addScore(double score) { 60 | this.scores.add(score); 61 | } 62 | 63 | public Profile getProfile() { 64 | return profile; 65 | } 66 | 67 | public void setProfile(Profile profile) { 68 | this.profile = profile; 69 | } 70 | 71 | public boolean isEnable() { 72 | return isEnable; 73 | } 74 | 75 | public void setEnable(boolean enable) { 76 | isEnable = enable; 77 | } 78 | 79 | public double getGpa() { 80 | double sum = 0; 81 | for (double score : scores) { 82 | sum += score; 83 | } 84 | gpa = sum / scores.size(); 85 | return gpa; 86 | } 87 | } 88 | 89 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/bindDemo/UserPropertyEntity.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.bindDemo; 2 | 3 | import javafx.beans.property.*; 4 | import javafx.collections.ObservableList; 5 | 6 | /** 7 | * @author suisui 8 | * @version 1.2 9 | * @description User的JavaFXBean 10 | * @date 2020/4/6 14:30 11 | * @since JavaFX2.0 JDK1.8 12 | */ 13 | public class UserPropertyEntity { 14 | private SimpleStringProperty name; 15 | private SimpleStringProperty password; 16 | private SimpleIntegerProperty age; 17 | private SimpleListProperty scores; 18 | private SimpleDoubleProperty gpa;//平均分 19 | private SimpleObjectProperty profile; 20 | private SimpleBooleanProperty enable; 21 | 22 | public String getName() { 23 | return name.get(); 24 | } 25 | 26 | public SimpleStringProperty nameProperty() { 27 | return name; 28 | } 29 | 30 | public void setName(String name) { 31 | this.name.set(name); 32 | } 33 | 34 | public String getPassword() { 35 | return password.get(); 36 | } 37 | 38 | public SimpleStringProperty passwordProperty() { 39 | return password; 40 | } 41 | 42 | public void setPassword(String password) { 43 | this.password.set(password); 44 | } 45 | 46 | public int getAge() { 47 | return age.get(); 48 | } 49 | 50 | public SimpleIntegerProperty ageProperty() { 51 | return age; 52 | } 53 | 54 | public void setAge(int age) { 55 | this.age.set(age); 56 | } 57 | 58 | public ObservableList getScores() { 59 | return scores.get(); 60 | } 61 | 62 | public SimpleListProperty scoresProperty() { 63 | return scores; 64 | } 65 | 66 | public void setScores(ObservableList scores) { 67 | this.scores.set(scores); 68 | } 69 | 70 | public double getGpa() { 71 | return gpa.get(); 72 | } 73 | 74 | public SimpleDoubleProperty gpaProperty() { 75 | return gpa; 76 | } 77 | 78 | public void setGpa(double gpa) { 79 | this.gpa.set(gpa); 80 | } 81 | 82 | public Profile getProfile() { 83 | return profile.get(); 84 | } 85 | 86 | public SimpleObjectProperty profileProperty() { 87 | return profile; 88 | } 89 | 90 | public void setProfile(Profile profile) { 91 | this.profile.set(profile); 92 | } 93 | 94 | public boolean getEnable() { 95 | return enable.get(); 96 | } 97 | 98 | public SimpleBooleanProperty enableProperty() { 99 | return enable; 100 | } 101 | 102 | public void setEnable(boolean enable) { 103 | this.enable.set(enable); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/firstDemo/FirstDemo.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.firstDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXScan; 4 | import cn.edu.scau.biubiusuisui.config.FXPlusApplication; 5 | import javafx.application.Application; 6 | import javafx.stage.Stage; 7 | 8 | /** 9 | * @author jack 10 | * @author suisui 11 | * @version 1.0 12 | * @description 第一个示例 13 | * @date 2020/1/1 23:06 14 | * @since JavaFX2.0 JDK1.8 15 | */ 16 | @FXScan(base = {"cn.edu.scau.biubiusuisui.example.firstDemo"}) //会扫描带FXController和FXEntity的类进行初始化 17 | public class FirstDemo extends Application { 18 | @Override 19 | public void start(Stage primaryStage) throws Exception { 20 | FXPlusApplication.start(FirstDemo.class); //其他配置和JavaFX相同,这里要调用FXPlusAppcalition的start方法,开始FX-plus加强 21 | } 22 | } -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/firstDemo/MainController.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.firstDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXController; 4 | import cn.edu.scau.biubiusuisui.annotation.FXWindow; 5 | import cn.edu.scau.biubiusuisui.entity.FXBaseController; 6 | import cn.edu.scau.biubiusuisui.entity.FXPlusContext; 7 | import cn.edu.scau.biubiusuisui.factory.FXEntityFactory; 8 | import javafx.beans.property.Property; 9 | import javafx.event.ActionEvent; 10 | import javafx.fxml.FXML; 11 | import javafx.fxml.Initializable; 12 | import javafx.scene.control.Button; 13 | import javafx.scene.control.ListView; 14 | 15 | import java.net.URL; 16 | import java.util.ResourceBundle; 17 | 18 | /** 19 | * @author jack 20 | * @author suisui 21 | * @version 1.0 22 | * @description 示例的主窗口 23 | * @date 2020/1/1 23:06 24 | * @since JavaFX2.0 JDK1.8 25 | */ 26 | @FXController(path = "fxml/firstDemo/firstDemo.fxml") 27 | @FXWindow(title = "firstDemo", mainStage = true) 28 | public class MainController extends FXBaseController implements Initializable { 29 | 30 | @FXML 31 | private Button addHelloButton; 32 | @FXML 33 | private Button deleteHelloButton; 34 | 35 | @FXML 36 | private ListView list; 37 | 38 | private Student student; 39 | 40 | @FXML 41 | void addWord(ActionEvent event) { 42 | student.addList("hello"); 43 | } 44 | 45 | @FXML 46 | void delWord(ActionEvent event) { 47 | student.delList("hello"); 48 | } 49 | 50 | @Override 51 | public void initialize(URL location, ResourceBundle resources) { 52 | student = (Student) FXEntityFactory.wrapFXBean(Student.class); // 从工厂中拿到将JavaBean转换得到的JavaFXBean 53 | Property listProperty = FXPlusContext.getEntityPropertyByName(student, "list"); 54 | list.itemsProperty().bind(listProperty); 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/firstDemo/Student.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.firstDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXEntity; 4 | import cn.edu.scau.biubiusuisui.annotation.FXField; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * @author suisui 11 | * @version 1.0 12 | * @description 13 | * @date 2020/1/1 23:07 14 | * @since JavaFX2.0 JDK1.8 15 | */ 16 | 17 | @FXEntity 18 | public class Student { 19 | 20 | @FXField //标记该属性是否被生成对应的Property 21 | private int age = 0; 22 | 23 | @FXField 24 | private List list = new ArrayList<>(); 25 | 26 | public void addList(String word) { 27 | list.add(word); 28 | } 29 | 30 | public void delList(String word) { 31 | list.remove(word); 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/languageDemo/ChineseController.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.languageDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXController; 4 | import cn.edu.scau.biubiusuisui.annotation.FXRedirect; 5 | import cn.edu.scau.biubiusuisui.annotation.FXWindow; 6 | import cn.edu.scau.biubiusuisui.entity.FXBaseController; 7 | import cn.edu.scau.biubiusuisui.entity.FXPlusLocale; 8 | import javafx.fxml.FXML; 9 | 10 | 11 | /** 12 | * @author suisui 13 | * @description 中文界面 14 | * @date 2020/5/3 16:23 15 | * @since JDK1.8 16 | */ 17 | @FXWindow(mainStage = true, title = "languageDemo") 18 | @FXController(path = "fxml/languageDemo/languageDemo.fxml", locale = FXPlusLocale.SIMPLIFIED_CHINESE) 19 | public class ChineseController extends FXBaseController { 20 | @FXML 21 | public void clickToChinese() { 22 | redirect("ChineseController"); 23 | } 24 | 25 | @FXML 26 | public void clickToEnglish() { 27 | redirect("EnglishController"); 28 | } 29 | 30 | @FXML 31 | public void clickToKorean() { 32 | redirect("KoreanController"); 33 | } 34 | 35 | @FXRedirect 36 | public String redirect(String name) { 37 | return name; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/languageDemo/EnglishController.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.languageDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXController; 4 | import cn.edu.scau.biubiusuisui.annotation.FXRedirect; 5 | import cn.edu.scau.biubiusuisui.annotation.FXWindow; 6 | import cn.edu.scau.biubiusuisui.entity.FXBaseController; 7 | import cn.edu.scau.biubiusuisui.entity.FXPlusLocale; 8 | import javafx.fxml.FXML; 9 | 10 | /** 11 | * @author suisui 12 | * @description 英文界面 13 | * @date 2020/5/3 19:54 14 | * @since JDK1.8 15 | */ 16 | @FXWindow(mainStage = false, title = "languageDemo") 17 | @FXController(path = "fxml/languageDemo/languageDemo.fxml", locale = FXPlusLocale.ENGLISH) 18 | public class EnglishController extends FXBaseController { 19 | @FXML 20 | public void clickToChinese() { 21 | redirect("ChineseController"); 22 | } 23 | 24 | @FXML 25 | public void clickToEnglish() { 26 | redirect("EnglishController"); 27 | } 28 | 29 | @FXML 30 | public void clickToKorean() { 31 | redirect("KoreanController"); 32 | } 33 | 34 | @FXRedirect 35 | public String redirect(String name) { 36 | return name; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/languageDemo/KoreanController.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.languageDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXController; 4 | import cn.edu.scau.biubiusuisui.annotation.FXRedirect; 5 | import cn.edu.scau.biubiusuisui.annotation.FXWindow; 6 | import cn.edu.scau.biubiusuisui.entity.FXBaseController; 7 | import cn.edu.scau.biubiusuisui.entity.FXPlusLocale; 8 | import javafx.fxml.FXML; 9 | 10 | /** 11 | * @author suisui 12 | * @description 法语界面 13 | * @date 2020/5/4 14:01 14 | * @since JDK1.8 15 | */ 16 | @FXWindow(mainStage = false, title = "languageDemo") 17 | @FXController(path = "fxml/languageDemo/languageDemo.fxml", locale = FXPlusLocale.KOREAN) 18 | public class KoreanController extends FXBaseController { 19 | @FXML 20 | public void clickToChinese() { 21 | redirect("ChineseController"); 22 | } 23 | 24 | @FXML 25 | public void clickToEnglish() { 26 | redirect("EnglishController"); 27 | } 28 | 29 | @FXML 30 | public void clickToKorean() { 31 | redirect("KoreanController"); 32 | } 33 | 34 | @FXRedirect 35 | public String redirect(String name) { 36 | return name; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/languageDemo/LanguageDemo.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.languageDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXScan; 4 | import cn.edu.scau.biubiusuisui.config.FXPlusApplication; 5 | import javafx.application.Application; 6 | import javafx.stage.Stage; 7 | 8 | /** 9 | * @author suisui 10 | * @description 测试语言国际化的Demo 11 | * @date 2020/5/3 09:57 12 | * @since JDK1.8 13 | */ 14 | @FXScan(base = "cn.edu.scau.biubiusuisui.example.languageDemo") 15 | public class LanguageDemo extends Application { 16 | @Override 17 | public void start(Stage primaryStage) throws Exception { 18 | FXPlusApplication.start(getClass()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/lifeDemo/DialogController.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.lifeDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXController; 4 | import cn.edu.scau.biubiusuisui.annotation.FXWindow; 5 | import cn.edu.scau.biubiusuisui.entity.FXBaseController; 6 | import cn.edu.scau.biubiusuisui.entity.FXPlusLocale; 7 | import cn.edu.scau.biubiusuisui.log.FXPlusLogger; 8 | import cn.edu.scau.biubiusuisui.log.FXPlusLoggerFactory; 9 | import cn.edu.scau.biubiusuisui.log.IFXPlusLogger; 10 | 11 | /** 12 | * @author suisui 13 | * @version 1.2 14 | * @description 弹窗 15 | * @date 2020/5/1 13:49 16 | * @since JavaFX2.0 JDK1.8 17 | */ 18 | @FXWindow(title = "Dialog") 19 | @FXController(path = "fxml/lifeDemo/dialog.fxml", locale = FXPlusLocale.SIMPLIFIED_CHINESE) 20 | 21 | public class DialogController extends FXBaseController { 22 | private static IFXPlusLogger logger = FXPlusLoggerFactory.getLogger(DialogController.class); 23 | 24 | @Override 25 | public void initialize() throws Exception { 26 | logger.info("DialogController----initialize"); 27 | } 28 | 29 | @Override 30 | public void onLoad() throws Exception { 31 | logger.info("DialogController----onLoad"); 32 | } 33 | 34 | @Override 35 | public void onShow() throws Exception { 36 | logger.info("DialogController----onShow"); 37 | } 38 | 39 | @Override 40 | public void onClose() throws Exception { 41 | logger.info("DialogController----onClose"); 42 | } 43 | 44 | @Override 45 | public void onHide() throws Exception { 46 | logger.info("DialogController----onHide"); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/lifeDemo/LifeDemo.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.lifeDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXScan; 4 | import cn.edu.scau.biubiusuisui.config.FXPlusApplication; 5 | import cn.edu.scau.biubiusuisui.log.FXPlusLoggerFactory; 6 | import cn.edu.scau.biubiusuisui.log.IFXPlusLogger; 7 | import cn.edu.scau.biubiusuisui.utils.LogUtil; 8 | import javafx.application.Application; 9 | import javafx.application.Platform; 10 | import javafx.stage.Stage; 11 | 12 | 13 | /** 14 | * @author suisui 15 | * @version 1.2 16 | * @description 测试生命周期的Demo 17 | * @date 2020/5/1 11:50 18 | * @since JavaFX2.0 JDK1.8 19 | */ 20 | @FXScan(base = "cn.edu.scau.biubiusuisui.example.lifeDemo") 21 | public class LifeDemo extends Application { 22 | private static IFXPlusLogger logger = FXPlusLoggerFactory.getLogger(LifeDemo.class); 23 | 24 | @Override 25 | public void start(Stage primaryStage) throws Exception { 26 | logger.info("LifeDemo---start"); 27 | // Platform.setImplicitExit(false); //设置当关闭最后一个Stage时,JavaFX应用程序不会自动退出 28 | FXPlusApplication.start(getClass()); 29 | } 30 | 31 | @Override 32 | public void init() throws Exception { 33 | logger.info("LifeDemo---init"); 34 | } 35 | 36 | @Override 37 | public void stop() throws Exception { 38 | logger.info("LifeDemo---stop"); 39 | } 40 | 41 | } 42 | 43 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/lifeDemo/MainController.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.lifeDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXRedirect; 4 | import cn.edu.scau.biubiusuisui.annotation.FXWindow; 5 | import cn.edu.scau.biubiusuisui.annotation.FXController; 6 | import cn.edu.scau.biubiusuisui.entity.FXBaseController; 7 | import cn.edu.scau.biubiusuisui.entity.FXPlusLocale; 8 | import cn.edu.scau.biubiusuisui.log.FXPlusLoggerFactory; 9 | import cn.edu.scau.biubiusuisui.log.IFXPlusLogger; 10 | import javafx.fxml.FXML; 11 | import javafx.scene.input.Clipboard; 12 | 13 | /** 14 | * @author suisui 15 | * @version 1.2 16 | * @description 主窗口 17 | * @date 2020/5/1 11:53 18 | * @since JavaFX2.0 JDK1.8 19 | */ 20 | @FXWindow(mainStage = true, title = "lifeDemo", icon = "image/icon.png") 21 | @FXController(path = "fxml/lifeDemo/lifeMain.fxml", locale = FXPlusLocale.SIMPLIFIED_CHINESE) 22 | public class MainController extends FXBaseController { 23 | private static IFXPlusLogger logger = FXPlusLoggerFactory.getLogger(FXBaseController.class); 24 | 25 | @Override 26 | public void initialize() throws Exception { 27 | logger.info("MainController----initialize"); 28 | } 29 | 30 | @Override 31 | public void onShow() throws Exception { 32 | logger.info("MainController----onShow"); 33 | } 34 | 35 | @Override 36 | public void onLoad() throws Exception { 37 | logger.info("MainController----onLoad"); 38 | } 39 | 40 | @Override 41 | public void onClose() throws Exception { 42 | logger.info("MainController----onClose"); 43 | } 44 | 45 | @Override 46 | public void onHide() throws Exception { 47 | logger.info("MainController----onHide"); 48 | } 49 | 50 | @FXML 51 | public void go() { 52 | redirectToDialog(); 53 | } 54 | 55 | @FXML 56 | public void goAndClose() { 57 | redirectToDialogAndClose(); 58 | } 59 | 60 | /** 61 | * 弹窗不关闭窗口 62 | */ 63 | @FXRedirect(close = false) 64 | public String redirectToDialog() { 65 | return "DialogController"; 66 | } 67 | 68 | /** 69 | * 弹窗并关闭本窗口 70 | */ 71 | @FXRedirect() 72 | public String redirectToDialogAndClose() { 73 | return "DialogController"; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/lifeDemo/SubController.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.lifeDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXController; 4 | import cn.edu.scau.biubiusuisui.entity.FXBaseController; 5 | import cn.edu.scau.biubiusuisui.entity.FXPlusLocale; 6 | import cn.edu.scau.biubiusuisui.log.FXPlusLoggerFactory; 7 | import cn.edu.scau.biubiusuisui.log.IFXPlusLogger; 8 | 9 | /** 10 | * @author suisui 11 | * @version 1.2 12 | * @description 子组件 13 | * @date 2020/5/1 13:48 14 | * @since JavaFX2.0 JDK1.8 15 | */ 16 | @FXController(path = "fxml/lifeDemo/subBar.fxml", locale = FXPlusLocale.SIMPLIFIED_CHINESE) 17 | public class SubController extends FXBaseController { 18 | private static IFXPlusLogger logger = FXPlusLoggerFactory.getLogger(SubController.class); 19 | 20 | @Override 21 | public void initialize() throws Exception { 22 | logger.info("SubController----initialize"); 23 | } 24 | 25 | @Override 26 | public void onShow() throws Exception { 27 | logger.info("SubController----onShow"); 28 | } 29 | 30 | @Override 31 | public void onLoad() throws Exception { 32 | logger.info("SubController----onLoad"); 33 | } 34 | 35 | @Override 36 | public void onClose() throws Exception { 37 | logger.info("SubController----onClose"); 38 | } 39 | 40 | @Override 41 | public void onHide() throws Exception { 42 | logger.info("SubController----onHide"); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/listDemo/ListDemo.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.listDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXScan; 4 | import cn.edu.scau.biubiusuisui.config.FXPlusApplication; 5 | import javafx.application.Application; 6 | import javafx.stage.Stage; 7 | 8 | /** 9 | * @author jack 10 | * @version 1.0 11 | * @date 2019/7/27 1:43 12 | * @since JavaFX2.0 JDK1.8 13 | */ 14 | @FXScan(base = "cn.edu.scau.biubiusuisui.example.listDemo") 15 | public class ListDemo extends Application { 16 | @Override 17 | public void start(Stage primaryStage) throws Exception { 18 | FXPlusApplication.start(getClass()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/listDemo/MainController.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.listDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXBind; 4 | import cn.edu.scau.biubiusuisui.annotation.FXController; 5 | import cn.edu.scau.biubiusuisui.annotation.FXData; 6 | import cn.edu.scau.biubiusuisui.annotation.FXWindow; 7 | import cn.edu.scau.biubiusuisui.entity.FXBaseController; 8 | import javafx.collections.FXCollections; 9 | import javafx.collections.ObservableList; 10 | import javafx.fxml.FXML; 11 | import javafx.scene.control.ListView; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | * @author jack 17 | * @version 1.0 18 | * @date 2019/7/27 1:43 19 | * @since JavaFX2.0 JDK1.8 20 | */ 21 | @FXController(path = "fxml/listDemo/listDemo.fxml") 22 | @FXWindow(title = "listDemo", mainStage = true) 23 | public class MainController extends FXBaseController { 24 | 25 | private static int count = 0; 26 | 27 | @FXData 28 | User user = new User(); 29 | 30 | @FXML 31 | @FXBind("items=${@toList(user.names)}") 32 | private ListView userNameListView; 33 | 34 | 35 | @FXML 36 | public void addUserName() { 37 | user.addNames("Jack\t" + (count++)); 38 | } 39 | 40 | public ObservableList toList(List list) { 41 | if (list == null) { 42 | return null; 43 | } 44 | return FXCollections.observableList(list); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/listDemo/User.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.listDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXEntity; 4 | import cn.edu.scau.biubiusuisui.annotation.FXField; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * @author jack 11 | * @version 1.0 12 | * @date 2019/7/27 12:19 13 | * @since JavaFX2.0 JDK1.8 14 | */ 15 | @FXEntity 16 | public class User { 17 | @FXField 18 | private String name; 19 | 20 | @FXField 21 | private String password; 22 | 23 | @FXField 24 | private List names = new ArrayList<>(); 25 | 26 | 27 | public User() { 28 | // names.add("hello "); 29 | // names.add("test"); 30 | } 31 | 32 | 33 | public void addNames(String name) { 34 | names.add(name); 35 | } 36 | 37 | public String getName() { 38 | return name; 39 | } 40 | 41 | public void setName(String name) { 42 | this.name = name; 43 | } 44 | 45 | public String getPassword() { 46 | return password; 47 | } 48 | 49 | public void setPassword(String password) { 50 | this.password = password; 51 | } 52 | 53 | public List getNames() { 54 | return names; 55 | } 56 | 57 | public void setNames(ArrayList names) { 58 | this.names = names; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/logDemo/LogDemo.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.logDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.example.lifeDemo.LifeDemo; 4 | import cn.edu.scau.biubiusuisui.log.FXPlusLoggerFactory; 5 | import cn.edu.scau.biubiusuisui.log.IFXPlusLogger; 6 | import cn.edu.scau.biubiusuisui.utils.LogUtil; 7 | 8 | /** 9 | * @author suisui 10 | * @description 测试日志的Demo 11 | * @date 2020/5/2 19:58 12 | * @since JDK1.8 13 | */ 14 | public class LogDemo { 15 | private static IFXPlusLogger logger = FXPlusLoggerFactory.getLogger(LogDemo.class); 16 | 17 | public void testLogger() { 18 | logger.info("info"); 19 | logger.error("error"); 20 | logger.debug("debug"); 21 | logger.warn("warn"); 22 | } 23 | 24 | public void testLogUtil() { 25 | LogUtil.info("info"); 26 | LogUtil.error("error"); 27 | LogUtil.debug("debug"); 28 | LogUtil.warn("warn"); 29 | } 30 | 31 | public static void main(String[] args) { 32 | LogDemo demo = new LogDemo(); 33 | demo.testLogger(); 34 | demo.testLogUtil(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/mqDemo/MQDemo.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.mqDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXScan; 4 | import cn.edu.scau.biubiusuisui.config.FXPlusApplication; 5 | import javafx.application.Application; 6 | import javafx.stage.Stage; 7 | 8 | /** 9 | * @author suisui 10 | * @version 1.1 11 | * @description 12 | * @date 2019/12/8 13:17 13 | * @since JavaFX2.0 JDK1.8 14 | */ 15 | @FXScan(base = "cn.edu.scau.biubiusuisui.example.mqDemo") 16 | public class MQDemo extends Application { 17 | 18 | @Override 19 | public void init() throws Exception { 20 | System.out.println("application init"); 21 | } 22 | 23 | @Override 24 | public void start(Stage primaryStage) throws Exception { 25 | System.out.println("application start"); 26 | FXPlusApplication.start(MQDemo.class); 27 | } 28 | 29 | @Override 30 | public void stop() throws Exception { 31 | System.out.println("application stop"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/mqDemo/MainController.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.mqDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXController; 4 | import cn.edu.scau.biubiusuisui.annotation.FXReceiver; 5 | import cn.edu.scau.biubiusuisui.annotation.FXWindow; 6 | import cn.edu.scau.biubiusuisui.entity.FXBaseController; 7 | import javafx.fxml.FXML; 8 | import javafx.scene.control.TextArea; 9 | 10 | /** 11 | * @author suisui 12 | * @version 1.2 13 | * @description 主界面 14 | * @date 2019/12/8 13:17 15 | * @since JavaFX2.0 JDK1.8 16 | */ 17 | @FXController(path = "fxml/mqDemo/main.fxml") 18 | @FXWindow(mainStage = true, title = "MQDemo") 19 | public class MainController extends FXBaseController { 20 | 21 | @FXML 22 | private TextArea outTA; 23 | 24 | /** 25 | * 接收者必须指定要订阅的[发送者类名:方法名] 26 | * 发送函数的返回值会注入到接收函数的参数中 27 | * 28 | * @param msg 29 | */ 30 | @FXReceiver(name = "TopBarController:sendToMain") 31 | public void handleTopBar(String msg) { 32 | // 处理导航栏的点击事件 33 | outTA.appendText(msg + "\n"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/mqDemo/TopBarController.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.mqDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXController; 4 | import cn.edu.scau.biubiusuisui.annotation.FXSender; 5 | import cn.edu.scau.biubiusuisui.entity.FXBaseController; 6 | import javafx.fxml.FXML; 7 | 8 | /** 9 | * @author suisui 10 | * @version 1.1 11 | * @description 导航栏示例 12 | * @date 2019/12/8 13:17 13 | * @since JavaFX2.0 JDK1.8 14 | */ 15 | @FXController(path = "fxml/mqDemo/topBar.fxml") 16 | public class TopBarController extends FXBaseController { 17 | 18 | @FXML 19 | public void indexClick() { 20 | sendToMain("点击[首页]"); 21 | } 22 | 23 | @FXML 24 | public void scoreClick() { 25 | sendToMain("点击[积分中心]"); 26 | } 27 | 28 | @FXML 29 | public void questionClick() { 30 | sendToMain("点击[问答中心]"); 31 | } 32 | 33 | @FXML 34 | public void selfClick() { 35 | sendToMain("点击[个人中心]"); 36 | } 37 | 38 | /** 39 | * 系统会通过发射信号,调用所有订阅这个发射信号函数的方法,从而响应信号 40 | * 41 | * @param msg 42 | * @return 43 | */ 44 | @FXSender //标注为信号发射函数 45 | public String sendToMain(String msg) { 46 | return msg; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/redirectDemo/DialogController.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.redirectDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXController; 4 | import cn.edu.scau.biubiusuisui.annotation.FXWindow; 5 | import cn.edu.scau.biubiusuisui.entity.FXBaseController; 6 | 7 | /** 8 | * @author suisui 9 | * @version 1.1 10 | * @description 11 | * @date 2019/12/4 21:00 12 | * @since JavaFX2.0 JDK1.8 13 | */ 14 | @FXController(path = "fxml/redirectDemo/dialog.fxml") 15 | @FXWindow(title = "弹窗") 16 | public class DialogController extends FXBaseController { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/redirectDemo/LoginController.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.redirectDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXController; 4 | import cn.edu.scau.biubiusuisui.annotation.FXRedirect; 5 | import cn.edu.scau.biubiusuisui.annotation.FXWindow; 6 | import cn.edu.scau.biubiusuisui.entity.FXBaseController; 7 | import cn.edu.scau.biubiusuisui.entity.FXRedirectParam; 8 | import javafx.fxml.FXML; 9 | import javafx.scene.control.PasswordField; 10 | import javafx.scene.control.TextField; 11 | 12 | import java.util.Date; 13 | 14 | /** 15 | * @author suisui 16 | * @version 1.1 17 | * @description 18 | * @date 2019/12/3 11:53 19 | * @since JavaFX2.0 JDK1.8 20 | */ 21 | @FXController(path = "fxml/redirectDemo/login.fxml") 22 | @FXWindow(title = "redirectDemo", mainStage = true) 23 | public class LoginController extends FXBaseController { 24 | 25 | @FXML 26 | private TextField usernameTF; 27 | 28 | @FXML 29 | private PasswordField passwordPF; 30 | 31 | @FXML 32 | public void registerClick() { 33 | redirectToRegister(); 34 | } 35 | 36 | @FXRedirect 37 | public String redirectToRegister() { 38 | return "RegisterController"; 39 | } 40 | 41 | @FXML 42 | @FXRedirect(close = false) //弹窗 43 | public String redirectToDialog() { 44 | return "DialogController"; 45 | } 46 | 47 | @FXML 48 | @FXRedirect //登录成功 Query方式 49 | public String redirectToSuccessWithQuery() { 50 | return "SuccessController?showType=0&username=" + usernameTF.getText() + "&password=" + passwordPF.getText(); 51 | } 52 | 53 | @FXML 54 | @FXRedirect //登录成功 Param方式 55 | public FXRedirectParam redirectToSuccessWithParam() { 56 | FXRedirectParam params = new FXRedirectParam("SuccessController"); 57 | params.addParam("username", usernameTF.getText()); 58 | params.addParam("password", passwordPF.getText()); 59 | params.addQuery("showType", "0"); 60 | return params; 61 | } 62 | 63 | @FXML 64 | @FXRedirect 65 | public FXRedirectParam redirectToSuccessWithAll() { 66 | FXRedirectParam params = new FXRedirectParam("SuccessController"); 67 | params.addParam("username", usernameTF.getText()); 68 | params.addParam("password", passwordPF.getText()); 69 | 70 | params.addQuery("token", new Date().toString()); 71 | params.addQuery("showType", "0"); 72 | return params; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/redirectDemo/RedirectDemo.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.redirectDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXScan; 4 | import cn.edu.scau.biubiusuisui.config.FXPlusApplication; 5 | import javafx.application.Application; 6 | import javafx.stage.Stage; 7 | 8 | /** 9 | * @author suisui 10 | * @version 1.1 11 | * @description 测试重定向功能的Application 12 | * @date 2019/12/3 11:52 13 | * @since JavaFX2.0 JDK1.8 14 | */ 15 | @FXScan(base = "cn.edu.scau.biubiusuisui.example.redirectDemo") 16 | public class RedirectDemo extends Application { 17 | 18 | @Override 19 | public void start(Stage primaryStage) throws Exception { 20 | FXPlusApplication.start(RedirectDemo.class); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/redirectDemo/RegisterController.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.redirectDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXController; 4 | import cn.edu.scau.biubiusuisui.annotation.FXRedirect; 5 | import cn.edu.scau.biubiusuisui.annotation.FXWindow; 6 | import cn.edu.scau.biubiusuisui.entity.FXBaseController; 7 | import cn.edu.scau.biubiusuisui.entity.FXRedirectParam; 8 | import javafx.fxml.FXML; 9 | import javafx.scene.control.Alert; 10 | import javafx.scene.control.PasswordField; 11 | import javafx.scene.control.TextField; 12 | 13 | /** 14 | * @author suisui 15 | * @version 1.1 16 | * @description 17 | * @date 2019/12/4 00:07 18 | * @since JavaFX2.0 JDK1.8 19 | */ 20 | @FXController(path = "fxml/redirectDemo/register.fxml") 21 | @FXWindow(title = "register") 22 | public class RegisterController extends FXBaseController { 23 | @FXML 24 | private TextField usernameTF; 25 | 26 | @FXML 27 | private TextField emailTF; 28 | 29 | @FXML 30 | private PasswordField passwordPF; 31 | 32 | @FXML 33 | private PasswordField confirmPasswordPF; 34 | 35 | @FXML 36 | public void registerClick() { 37 | if (validate()) { 38 | UserEntity userEntity = new UserEntity(); 39 | userEntity.setUsername(usernameTF.getText()); 40 | userEntity.setPassword(passwordPF.getText()); 41 | userEntity.setEmail(emailTF.getText()); 42 | redirectToRegisterSuccess(userEntity); 43 | } 44 | } 45 | 46 | @FXML 47 | public void loginClick() { 48 | redirectToLogin(); 49 | } 50 | 51 | @FXRedirect 52 | public String redirectToLogin() { 53 | return "LoginController"; 54 | } 55 | 56 | @FXRedirect 57 | public FXRedirectParam redirectToRegisterSuccess(UserEntity userEntity) { 58 | FXRedirectParam fxRedirectParam = new FXRedirectParam("SuccessController"); 59 | fxRedirectParam.addQuery("showType", "1"); 60 | fxRedirectParam.addParam("user", userEntity); 61 | return fxRedirectParam; 62 | } 63 | 64 | // 校验 65 | private boolean validate() { 66 | boolean retCode = false; 67 | if (null != passwordPF.getText() && null != confirmPasswordPF.getText()) { 68 | if (!passwordPF.getText().equals(confirmPasswordPF.getText())) { 69 | retCode = false; 70 | new Alert(Alert.AlertType.ERROR, "两次密码不一致"); 71 | } else { 72 | retCode = true; 73 | } 74 | } else if (null == usernameTF.getText()) { 75 | retCode = false; 76 | new Alert(Alert.AlertType.ERROR, "用户名不能为空"); 77 | } else if (null == emailTF.getText()) { 78 | retCode = false; 79 | new Alert(Alert.AlertType.ERROR, "邮箱不能为空"); 80 | } 81 | return retCode; 82 | } 83 | 84 | private void clearAllInput() { 85 | usernameTF.setText(""); 86 | emailTF.setText(""); 87 | passwordPF.setText(""); 88 | confirmPasswordPF.setText(""); 89 | } 90 | } 91 | 92 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/redirectDemo/SuccessController.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.redirectDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXController; 4 | import cn.edu.scau.biubiusuisui.annotation.FXRedirect; 5 | import cn.edu.scau.biubiusuisui.annotation.FXWindow; 6 | import cn.edu.scau.biubiusuisui.entity.FXBaseController; 7 | import javafx.fxml.FXML; 8 | import javafx.scene.control.Label; 9 | 10 | /** 11 | * @author suisui 12 | * @version 1.1 13 | * @description 登录成功的Controller 14 | * @date 2019/12/3 12:43 15 | * @since JavaFX2.0 JDK1.8 16 | */ 17 | @FXController(path = "fxml/redirectDemo/success.fxml") 18 | @FXWindow(title = "success") 19 | public class SuccessController extends FXBaseController { 20 | 21 | @FXML 22 | private Label title; 23 | 24 | @FXML 25 | private Label usernameLabel; 26 | 27 | @FXML 28 | private Label passwordLabel; 29 | 30 | @FXML 31 | private Label tokenLabel; 32 | 33 | @FXML 34 | @FXRedirect 35 | public String redirectToLogin() { 36 | return "LoginController"; 37 | } 38 | 39 | @Override 40 | public void onShow() { 41 | try { 42 | super.onShow(); 43 | } catch (Exception e) { 44 | e.printStackTrace(); 45 | } 46 | if (this.getQuery().get("showType") != null) { 47 | String showType = (String) this.getQuery().get("showType"); 48 | if (showType.equals("1")) { //注册 49 | title.setText("注册成功"); 50 | if (this.getParam().get("user") != null) { 51 | UserEntity userEntity = (UserEntity) this.getParam().get("user"); 52 | usernameLabel.setText(userEntity.getUsername()); 53 | passwordLabel.setText(userEntity.getPassword()); 54 | } 55 | } else { //登录 56 | title.setText("登录成功"); 57 | // 此处为演示多种方式数据传递才进行多次赋值,实际应用时应根据数据API进行相应的数据获取操作 58 | if (this.getQuery().size() > 1) { //query方式传递 59 | usernameLabel.setText(String.valueOf(this.getQuery().get("username"))); 60 | passwordLabel.setText(String.valueOf(this.getQuery().get("password"))); 61 | tokenLabel.setText(String.valueOf(this.getQuery().get("token"))); 62 | } 63 | if (this.getParam().size() > 1) { //param方式传递 64 | usernameLabel.setText(String.valueOf(this.getParam().get("username"))); 65 | passwordLabel.setText(String.valueOf(this.getParam().get("password"))); 66 | } 67 | } 68 | } 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/redirectDemo/UserEntity.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.redirectDemo; 2 | 3 | /** 4 | * @author suisui 5 | * @version 1.1 6 | * @description 简单的用户实体 7 | * @date 2020/1/14 22:39 8 | * @since JavaFX2.0 JDK1.8 9 | */ 10 | public class UserEntity { 11 | private String username; 12 | private String password; 13 | private String email; 14 | 15 | 16 | public String getUsername() { 17 | return username; 18 | } 19 | 20 | public void setUsername(String username) { 21 | this.username = username; 22 | } 23 | 24 | public String getPassword() { 25 | return password; 26 | } 27 | 28 | public void setPassword(String password) { 29 | this.password = password; 30 | } 31 | 32 | public String getEmail() { 33 | return email; 34 | } 35 | 36 | public void setEmail(String email) { 37 | this.email = email; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/resizableDemo/MainController.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.resizableDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXController; 4 | import cn.edu.scau.biubiusuisui.annotation.FXWindow; 5 | import cn.edu.scau.biubiusuisui.entity.FXBaseController; 6 | import javafx.fxml.FXML; 7 | import javafx.stage.StageStyle; 8 | 9 | /** 10 | * @author suisui 11 | * @version 1.2 12 | * @description 主控制器 13 | * @date 2020/4/5 00:05 14 | * @since JavaFX2.0 JDK1.8 15 | */ 16 | @FXController(path = "fxml/resizableDemo/resizableDemo.fxml") 17 | @FXWindow(mainStage = true, title = "resizableDemo", draggable = true, resizable = true, style = StageStyle.UNDECORATED) 18 | public class MainController extends FXBaseController { 19 | 20 | @FXML 21 | public void closeWindowClick() { 22 | this.closeStage(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/example/resizableDemo/ResizableDemo.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.example.resizableDemo; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXScan; 4 | import cn.edu.scau.biubiusuisui.config.FXPlusApplication; 5 | import javafx.application.Application; 6 | import javafx.stage.Stage; 7 | 8 | /** 9 | * @author suisui 10 | * @version 1.0 11 | * @description 缩放和拖拽的示例 12 | * @date 2020/4/5 00:04 13 | * @since JavaFX2.0 JDK1.8 14 | */ 15 | @FXScan(base = "cn.edu.scau.biubiusuisui.example.resizableDemo") 16 | public class ResizableDemo extends Application { 17 | @Override 18 | public void start(Stage primaryStage) throws Exception { 19 | FXPlusApplication.start(ResizableDemo.class); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/exception/InvalidURLException.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.exception; 2 | 3 | /** 4 | * @author suisui 5 | * @version 1.2 6 | * @description 不合法URL 7 | * @date 2020/4/6 15:59 8 | * @since JavaFX2.0 JDK1.8 9 | */ 10 | public class InvalidURLException extends Exception { 11 | public InvalidURLException() { 12 | super("the url is invalid"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/exception/NoSuchChangeMethod.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.exception; 2 | 3 | /** 4 | * @author jack 5 | * @version 1.0 6 | * @date 2019/7/27 3:00 7 | * @since JavaFX2.0 JDK1.8 8 | */ 9 | public class NoSuchChangeMethod extends Exception { 10 | 11 | public NoSuchChangeMethod() { 12 | super("No such change method"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/exception/NotFXWindowException.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.exception; 2 | 3 | /** 4 | * @author suisui 5 | * @version 1.2 6 | * @description 某Controller不是窗口的错误 7 | * @date 2020/4/6 17:10 8 | * @since JavaFX2.0 JDK1.8 9 | */ 10 | public class NotFXWindowException extends Exception { 11 | public NotFXWindowException() { 12 | super("the controller is not a window"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/exception/ProtocolNotSupport.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.exception; 2 | 3 | /** 4 | * @author jack 5 | * @version 1.0 6 | * @date 2019/6/25 7:23 7 | * @since JavaFX2.0 JDK1.8 8 | */ 9 | public class ProtocolNotSupport extends Exception { 10 | public ProtocolNotSupport() { 11 | super("protocolNotSupport"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/expression/BindParser.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.expression; 2 | 3 | /** 4 | * @author jack 5 | * @version 1.0 6 | * @date 2019/7/27 2:02 7 | * @since JavaFX2.0 JDK1.8 8 | */ 9 | public interface BindParser { 10 | public void parse(Object target, String expression); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/expression/action/ChangeParser.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.expression.action; 2 | 3 | import cn.edu.scau.biubiusuisui.expression.BindParser; 4 | 5 | /** 6 | * @author jack 7 | * @version 1.0 8 | * @date 2019/7/27 2:03 9 | * @since JavaFX2.0 JDK1.8 10 | */ 11 | public class ChangeParser implements BindParser { 12 | 13 | @Override 14 | public void parse(Object target, String expression) { 15 | 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/expression/data/ExpFunction.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.expression.data; 2 | 3 | /** 4 | * @author jack 5 | * @version 1.0 6 | * @date 2019/7/27 20:03 7 | * @since JavaFX2.0 JDK1.8 8 | */ 9 | @FunctionalInterface 10 | public interface ExpFunction { 11 | R apply(T t, U u); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/expression/data/ExpressionParser.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.expression.data; 2 | 3 | 4 | import cn.edu.scau.biubiusuisui.annotation.FXValue; 5 | import cn.edu.scau.biubiusuisui.exception.NoSuchChangeMethod; 6 | import com.sun.istack.internal.NotNull; 7 | import com.sun.javafx.fxml.expression.Expression; 8 | import javafx.beans.property.Property; 9 | 10 | import java.lang.reflect.InvocationTargetException; 11 | import java.lang.reflect.Method; 12 | import java.lang.reflect.Parameter; 13 | 14 | /** 15 | * 将FXBind中表达式建立绑定 16 | * 格式如下 17 | * 语法如下: 18 | * FXBind("S") 19 | * S -> left=right 20 | * left -> property 21 | * right -> ${expression} 22 | * expression -> bean.field 23 | *

24 | * FXBind("text=${bean.field}) 25 | * textProperty 通过 adapter.getModelProperty --> textProperty实例 26 | * bean 通过namespace 获取,因为bean有FXEntity标签,所以返回包装过后的bean的property 27 | * 最后 28 | * left.bind(right) 29 | * 30 | * @author jack 31 | * @version 1.0 32 | * @date 2019/7/23 15:05 33 | * @since JavaFX2.0 JDK1.8 34 | */ 35 | public class ExpressionParser { 36 | 37 | private Object namespace; 38 | private Object targetController; 39 | private static final String BIND_PREFIX = "${"; 40 | private static final String BIND_SUFIX = "}"; 41 | private static final String PROEPRTY = "Property"; 42 | 43 | public enum ExpressionType { 44 | DataExpression, 45 | ActionExpression 46 | } 47 | 48 | public ExpressionParser(Object namespace, Object targetController) { 49 | this.namespace = namespace; 50 | this.targetController = targetController; 51 | } 52 | 53 | public ExpressionParser(Object namespace) { 54 | this.namespace = namespace; 55 | } 56 | 57 | private Property getLeftProperty(MyBeanAdapter myBeanAdapter, String key) { 58 | return (Property) myBeanAdapter.getPropertyModel(key); 59 | } 60 | 61 | private static final String FUNCTION_PREFIX = "@"; 62 | 63 | private MyExpressionValue getRightExpression(MyBeanAdapter myBeanAdapter, String key, String rightExpression) { 64 | Expression expression = null; 65 | if (rightExpression.startsWith(FUNCTION_PREFIX)) { 66 | expression = getFunctionExpression(rightExpression); 67 | } else { 68 | expression = Expression.valueOf(rightExpression); 69 | } 70 | Class clazz = myBeanAdapter.getType(key); 71 | MyExpressionValue myExpressionValue = new MyExpressionValue(namespace, expression, clazz); 72 | return myExpressionValue; 73 | } 74 | 75 | private Expression getFunctionExpression(String rightExpression) { 76 | Expression expression = null; 77 | int indexLeft = rightExpression.indexOf("("); 78 | String methodName = rightExpression.substring(1, indexLeft); 79 | int indexRight = rightExpression.indexOf(")"); 80 | String argString = rightExpression.substring(indexLeft + 1, indexRight); 81 | String[] args = null; 82 | if (!"".equals(argString.trim())) { 83 | args = argString.split(","); 84 | } 85 | Class targetClazz = targetController.getClass(); 86 | Method[] methods = targetClazz.getMethods(); 87 | Expression[] expressionArgs = null; 88 | if (args != null) { 89 | expressionArgs = new Expression[args.length]; 90 | for (int i = 0; i < args.length; i++) { 91 | if (!"".equals(args[i].trim())) { 92 | expressionArgs[i] = Expression.valueOf(args[i]); 93 | } 94 | } 95 | } 96 | for (Method method : methods) { 97 | if (method.getName().equals(methodName)) { 98 | expression = new FunctionExpression(method, targetController, expressionArgs); 99 | } 100 | } 101 | return expression; 102 | } 103 | 104 | public void parse(Object object, @NotNull String expression) throws NoSuchChangeMethod { 105 | //check expression 106 | int index = expression.indexOf("="); 107 | if (index == -1) { 108 | return; 109 | } 110 | String[] items = expression.split("="); 111 | if (items.length != 2) { 112 | return; 113 | } 114 | String left = items[0]; 115 | String right = items[1]; 116 | if (left == null || right == null) { 117 | return; 118 | } 119 | right = right.trim(); 120 | ExpressionType expressionType; 121 | if (right.startsWith(BIND_PREFIX) && right.endsWith(BIND_SUFIX)) { 122 | int length = right.length(); 123 | right = right.substring(2, length - 1); //已经去掉“${”的表达式 124 | expressionType = ExpressionType.DataExpression; 125 | } else { 126 | right = right.substring(1); //#changeMethod -> changeMethod 127 | expressionType = ExpressionType.ActionExpression; 128 | } 129 | MyBeanAdapter myBeanAdapter = new MyBeanAdapter(object); 130 | Property leftProperty = getLeftProperty(myBeanAdapter, left); 131 | switch (expressionType) { 132 | case DataExpression: 133 | bindDataExpression(left, right, myBeanAdapter, leftProperty); 134 | break; 135 | case ActionExpression: 136 | bindActionExpression(right, leftProperty); 137 | } 138 | } 139 | 140 | /** 141 | * @param right 142 | * @param leftProperty 143 | * @throws NoSuchChangeMethod 144 | * @Description 鼠标事件或键盘事件绑定 145 | */ 146 | private void bindActionExpression(String right, Property leftProperty) throws NoSuchChangeMethod { 147 | Class clazz = targetController.getClass(); 148 | Method[] methods = clazz.getMethods(); 149 | for (Method method : methods) { 150 | if (method.getName().equals(right)) { 151 | leftProperty.addListener((observable, oldValue, newValue) -> { 152 | try { 153 | Object[] objects = getArgs(method, observable, newValue, oldValue); 154 | method.invoke(targetController, objects); 155 | } catch (IllegalAccessException e) { 156 | e.printStackTrace(); 157 | } catch (InvocationTargetException e) { 158 | e.printStackTrace(); 159 | } 160 | }); 161 | } 162 | } 163 | } 164 | 165 | /** 166 | * @param left 167 | * @param right 168 | * @param myBeanAdapter 169 | * @param leftProperty 170 | * @Description 数据绑定 171 | */ 172 | private void bindDataExpression(String left, String right, MyBeanAdapter myBeanAdapter, Property leftProperty) { 173 | MyExpressionValue rightProperty = getRightExpression(myBeanAdapter, left, right); 174 | leftProperty.bind(rightProperty); 175 | } 176 | 177 | public Object[] getArgs(Method method, Object... args) { 178 | Parameter[] parameters = method.getParameters(); 179 | Object[] objects = new Object[parameters.length]; 180 | for (int i = 0; i < parameters.length; i++) { 181 | FXValue annotation = parameters[i].getAnnotation(FXValue.class); 182 | switch (annotation.value()) { 183 | case "target": 184 | objects[i] = args[0]; 185 | break; 186 | case "newValue": 187 | objects[i] = args[1]; 188 | break; 189 | case "oldValue": 190 | objects[i] = args[2]; 191 | break; 192 | } 193 | } 194 | return objects; 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/expression/data/FunctionExpression.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.expression.data; 2 | 3 | import com.sun.javafx.fxml.expression.Expression; 4 | import com.sun.javafx.fxml.expression.KeyPath; 5 | 6 | import java.lang.reflect.InvocationTargetException; 7 | import java.lang.reflect.Method; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | /** 12 | * @author jack 13 | * @version 1.0 14 | * @date 2019/7/27 20:00 15 | * @since JavaFX2.0 JDK1.8 16 | */ 17 | public class FunctionExpression extends Expression { 18 | 19 | private Method method; 20 | private Object target; 21 | private Expression[] args; 22 | 23 | public FunctionExpression(Method method, Object target, Expression[] expressions) { 24 | this.method = method; 25 | this.target = target; 26 | this.args = expressions; 27 | } 28 | 29 | @Override 30 | public List getArguments() { 31 | List list = new ArrayList<>(); 32 | if (args != null) { 33 | for (Expression expression : args) { 34 | list.addAll(expression.getArguments()); 35 | } 36 | } 37 | return list; 38 | } 39 | 40 | @Override 41 | public Object evaluate(Object namespace) { 42 | Object result = null; 43 | if (args != null) { 44 | Object[] values = new Object[args.length]; 45 | for (int i = 0; i < args.length; i++) { 46 | values[i] = args[i].evaluate(namespace); 47 | } 48 | try { 49 | result = method.invoke(target, values); 50 | } catch (IllegalAccessException e) { 51 | e.printStackTrace(); 52 | } catch (InvocationTargetException e) { 53 | e.printStackTrace(); 54 | } 55 | return result; 56 | } else { 57 | try { 58 | result = method.invoke(target); 59 | } catch (IllegalAccessException e) { 60 | e.printStackTrace(); 61 | } catch (InvocationTargetException e) { 62 | e.printStackTrace(); 63 | } 64 | } 65 | return result; 66 | } 67 | 68 | @Override 69 | public void update(Object namespace, Object value) { 70 | 71 | } 72 | 73 | @Override 74 | public boolean isDefined(Object namespace) { 75 | return false; 76 | } 77 | 78 | @Override 79 | public boolean isLValue() { 80 | return false; 81 | } 82 | 83 | @Override 84 | protected void getArguments(List arguments) { 85 | 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/expression/data/MyBeanAdapter.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.expression.data; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXEntity; 4 | import cn.edu.scau.biubiusuisui.entity.FXPlusContext; 5 | import cn.edu.scau.biubiusuisui.utils.BeanUtil; 6 | import com.sun.javafx.fxml.BeanAdapter; 7 | import javafx.beans.value.ObservableValue; 8 | 9 | /** 10 | * @author jack 11 | * @version 1.0 12 | * @date 2019/7/23 15:16 13 | * @since JavaFX2.0 JDK1.8 14 | */ 15 | public class MyBeanAdapter extends BeanAdapter { 16 | 17 | private Object object; 18 | 19 | /** 20 | * Creates a new Bean adapter. 21 | * 22 | * @param bean The Bean object to wrap. 23 | */ 24 | public MyBeanAdapter(Object bean) { 25 | super(bean); 26 | this.object = bean; 27 | } 28 | 29 | @Override 30 | public ObservableValue getPropertyModel(String key) { 31 | if (object.getClass().getAnnotation(FXEntity.class) == null) { 32 | return super.getPropertyModel(key); 33 | } else { 34 | return BeanUtil.getPropertyByName(object, key); 35 | } 36 | } 37 | 38 | public String valueOf(String value) { 39 | return value; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/expression/data/MyExpressionValue.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.expression.data; 2 | 3 | import com.sun.javafx.fxml.BeanAdapter; 4 | import com.sun.javafx.fxml.expression.Expression; 5 | import com.sun.javafx.fxml.expression.KeyPath; 6 | import javafx.beans.InvalidationListener; 7 | import javafx.beans.value.ChangeListener; 8 | import javafx.beans.value.ObservableValue; 9 | import javafx.beans.value.ObservableValueBase; 10 | import javafx.collections.ListChangeListener; 11 | import javafx.collections.MapChangeListener; 12 | import javafx.collections.ObservableList; 13 | import javafx.collections.ObservableMap; 14 | 15 | import java.util.ArrayList; 16 | import java.util.Iterator; 17 | import java.util.List; 18 | 19 | /** 20 | * @author jack 21 | * @version 1.0 22 | * @since JavaFX2.0 JDK1.8 23 | */ 24 | public class MyExpressionValue extends ObservableValueBase { 25 | 26 | // Monitors a namespace for changes along a key path 27 | private class KeyPathMonitor { 28 | private String key; 29 | private KeyPathMonitor next; 30 | 31 | private Object namespace = null; 32 | 33 | private ListChangeListener listChangeListener = new ListChangeListener() { 34 | @Override 35 | public void onChanged(Change change) { 36 | while (change.next()) { 37 | int index = Integer.parseInt(key); 38 | 39 | if (index >= change.getFrom() && index < change.getTo()) { 40 | fireValueChangedEvent(); 41 | remonitor(); 42 | } 43 | } 44 | } 45 | }; 46 | 47 | private MapChangeListener mapChangeListener = new MapChangeListener() { 48 | @Override 49 | public void onChanged(Change change) { 50 | if (key.equals(change.getKey())) { 51 | fireValueChangedEvent(); 52 | remonitor(); 53 | } 54 | } 55 | }; 56 | 57 | private ChangeListener propertyChangeListener = new ChangeListener() { 58 | @Override 59 | public void changed(ObservableValue observable, Object oldValue, Object newValue) { 60 | fireValueChangedEvent(); 61 | remonitor(); 62 | } 63 | }; 64 | 65 | public KeyPathMonitor(Iterator keyPathIterator) { 66 | this.key = keyPathIterator.next(); 67 | 68 | if (keyPathIterator.hasNext()) { 69 | next = new KeyPathMonitor(keyPathIterator); 70 | } else { 71 | next = null; 72 | } 73 | } 74 | 75 | @SuppressWarnings("unchecked") 76 | public void monitor(Object namespace) { 77 | if (namespace instanceof ObservableList) { 78 | ((ObservableList) namespace).addListener(listChangeListener); 79 | } else if (namespace instanceof ObservableMap) { 80 | ((ObservableMap) namespace).addListener(mapChangeListener); 81 | } else { 82 | 83 | MyBeanAdapter namespaceAdapter = new MyBeanAdapter(namespace); 84 | ObservableValue propertyModel = namespaceAdapter.getPropertyModel(key); 85 | 86 | if (propertyModel != null) { 87 | propertyModel.addListener(propertyChangeListener); 88 | } 89 | 90 | namespace = namespaceAdapter; 91 | } 92 | 93 | this.namespace = namespace; 94 | 95 | if (next != null) { 96 | Object value = Expression.get(namespace, key); 97 | if (value != null) { 98 | next.monitor(value); 99 | } 100 | } 101 | } 102 | 103 | @SuppressWarnings("unchecked") 104 | public void unmonitor() { 105 | if (namespace instanceof ObservableList) { 106 | ((ObservableList) namespace).removeListener(listChangeListener); 107 | } else if (namespace instanceof ObservableMap) { 108 | ((ObservableMap) namespace).removeListener(mapChangeListener); 109 | } else if (namespace != null) { 110 | MyBeanAdapter namespaceAdapter = (MyBeanAdapter) namespace; 111 | ObservableValue propertyModel = namespaceAdapter.getPropertyModel(key); 112 | 113 | if (propertyModel != null) { 114 | propertyModel.removeListener(propertyChangeListener); 115 | } 116 | } 117 | 118 | namespace = null; 119 | 120 | if (next != null) { 121 | next.unmonitor(); 122 | } 123 | } 124 | 125 | public void remonitor() { 126 | if (next != null) { 127 | next.unmonitor(); 128 | Object value = Expression.get(namespace, key); 129 | if (value != null) { 130 | next.monitor(value); 131 | } 132 | } 133 | } 134 | } 135 | 136 | private Object namespace; 137 | private Expression expression; 138 | private Class type; 139 | 140 | private ArrayList argumentMonitors; 141 | 142 | private int listenerCount = 0; 143 | 144 | public MyExpressionValue(Object namespace, Expression expression, Class type) { 145 | if (namespace == null) { 146 | throw new NullPointerException(); 147 | } 148 | 149 | if (expression == null) { 150 | throw new NullPointerException(); 151 | } 152 | 153 | if (type == null) { 154 | throw new NullPointerException(); 155 | } 156 | 157 | this.namespace = namespace; 158 | this.expression = expression; 159 | this.type = type; 160 | 161 | List arguments = expression.getArguments(); 162 | argumentMonitors = new ArrayList(arguments.size()); 163 | 164 | for (KeyPath argument : arguments) { 165 | argumentMonitors.add(new KeyPathMonitor(argument.iterator())); 166 | } 167 | } 168 | 169 | @Override 170 | public Object getValue() { 171 | return BeanAdapter.coerce(expression.evaluate(namespace), type); 172 | } 173 | 174 | @Override 175 | public void addListener(InvalidationListener listener) { 176 | if (listenerCount == 0) { 177 | monitorArguments(); 178 | } 179 | 180 | super.addListener(listener); 181 | listenerCount++; 182 | } 183 | 184 | @Override 185 | public void removeListener(InvalidationListener listener) { 186 | super.removeListener(listener); 187 | listenerCount--; 188 | 189 | if (listenerCount == 0) { 190 | unmonitorArguments(); 191 | } 192 | } 193 | 194 | @Override 195 | public void addListener(ChangeListener listener) { 196 | if (listenerCount == 0) { 197 | monitorArguments(); 198 | } 199 | 200 | super.addListener(listener); 201 | listenerCount++; 202 | } 203 | 204 | @Override 205 | public void removeListener(ChangeListener listener) { 206 | super.removeListener(listener); 207 | listenerCount--; 208 | 209 | if (listenerCount == 0) { 210 | unmonitorArguments(); 211 | } 212 | } 213 | 214 | private void monitorArguments() { 215 | for (KeyPathMonitor argumentMonitor : argumentMonitors) { 216 | argumentMonitor.monitor(namespace); 217 | } 218 | } 219 | 220 | private void unmonitorArguments() { 221 | for (KeyPathMonitor argumentMonitor : argumentMonitors) { 222 | argumentMonitor.unmonitor(); 223 | } 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/factory/BeanBuilder.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.factory; 2 | 3 | /** 4 | * @author jack 5 | * @version 1.0 6 | * @date 2019/7/4 11:16 7 | * @since JavaFX2.0 JDK1.8 8 | */ 9 | public interface BeanBuilder { 10 | /** 11 | * 万能工厂方法 12 | * 13 | * @param type 类型 14 | * @return 实例对象 15 | */ 16 | Object getBean(Class type); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/factory/FXBuilder.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.factory; 2 | 3 | import cn.edu.scau.biubiusuisui.log.FXPlusLoggerFactory; 4 | import cn.edu.scau.biubiusuisui.log.IFXPlusLogger; 5 | 6 | /** 7 | * @author jack 8 | * @version 1.0 9 | * @date 2019/7/4 11:13 10 | * @since JavaFX2.0 JDK1.8 11 | */ 12 | public class FXBuilder implements BeanBuilder { 13 | private IFXPlusLogger logger = FXPlusLoggerFactory.getLogger(FXBuilder.class); 14 | 15 | @Override 16 | public Object getBean(Class type) { 17 | Object object = null; 18 | try { 19 | object = type.newInstance(); 20 | } catch (InstantiationException e) { 21 | logger.error(e.getMessage()); 22 | e.printStackTrace(); 23 | } catch (IllegalAccessException e) { 24 | logger.error(e.getMessage()); 25 | e.printStackTrace(); 26 | } 27 | return object; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/factory/FXEntityFactory.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.factory; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXField; 4 | import cn.edu.scau.biubiusuisui.entity.FXFieldWrapper; 5 | import cn.edu.scau.biubiusuisui.entity.FXPlusContext; 6 | import cn.edu.scau.biubiusuisui.proxy.FXEntityProxy; 7 | import cn.edu.scau.biubiusuisui.utils.ClassUtil; 8 | import javafx.beans.property.*; 9 | import javafx.collections.FXCollections; 10 | 11 | import java.lang.annotation.Annotation; 12 | import java.lang.reflect.Field; 13 | import java.util.HashMap; 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | /** 18 | * @author jack 19 | * @version 1.0 20 | * @date 2019/6/28 1:12 21 | * @since JavaFX2.0 JDK1.8 22 | */ 23 | public class FXEntityFactory { 24 | 25 | private FXEntityFactory() { 26 | } 27 | 28 | public static Object wrapFXBean(Class clazz) { 29 | return wrapFXBean(clazz, new FXBuilder()); 30 | } 31 | 32 | public static Object wrapFXBean(Class clazz, BeanBuilder beanBuilder) { 33 | Object object = null; 34 | object = beanBuilder.getBean(clazz); 35 | if (object != null) { 36 | return wrapFXBean(object); 37 | } else { 38 | return null; 39 | } 40 | } 41 | 42 | /** 43 | * @param object 被转换的对象 44 | * @return 45 | */ 46 | public static Object wrapFXBean(Object object) { 47 | FXEntityProxy fxEntityProxy = new FXEntityProxy(); 48 | Object proxyObject = null; 49 | try { 50 | proxyObject = fxEntityProxy.getInstance(object); // 初始化代理类 51 | processFXEntityProxyFields(object, proxyObject, fxEntityProxy); //处理FXEntity上的@FXField 52 | FXPlusContext.setProxyByBeanObject(proxyObject, fxEntityProxy); 53 | } catch (IllegalAccessException e) { 54 | e.printStackTrace(); 55 | } 56 | return proxyObject; 57 | } 58 | 59 | /** 60 | * @param entityObject 被转换的原Entity对象 61 | * @param proxyObject 被转换对象的FXEntityProxy对象 62 | * @param fxEntityProxy 被转换对象的FXEntityProxy类 63 | * @throws IllegalAccessException 64 | * @Description 处理FXEntity中的FXField注解,1. 添加监听 2.赋值FXEntityProxy中的fxFieldWrapperMap 65 | */ 66 | private static void processFXEntityProxyFields(Object entityObject, Object proxyObject, FXEntityProxy fxEntityProxy) throws IllegalAccessException { 67 | Map fxFieldWrapperMap = new HashMap<>(); 68 | Field[] fields = entityObject.getClass().getDeclaredFields(); 69 | for (Field field : fields) { 70 | Annotation annotation = ClassUtil.getAnnotationInList(FXField.class, field.getDeclaredAnnotations()); 71 | if (annotation != null) { 72 | Property property = null; 73 | field.setAccessible(true); 74 | FXField fxField = (FXField) annotation; 75 | FXFieldWrapper fieldWrapper = new FXFieldWrapper(fxField, field.getType()); 76 | if (field.get(entityObject) == null) { //没有初始值 77 | property = getFieldDefaultProperty(field); 78 | } else { //有初始值 79 | property = getFieldProperty(entityObject, field); 80 | } 81 | if (property != null) { 82 | // 监听 83 | property.addListener((object, oldVal, newVal) -> { 84 | if (!fxField.readOnly()) { 85 | // 判断field.getType()是否为List类型 86 | if (!List.class.isAssignableFrom(field.getType())) { 87 | try { 88 | field.set(proxyObject, newVal);//赋值 89 | } catch (IllegalAccessException e) { 90 | e.printStackTrace(); 91 | } 92 | } 93 | } 94 | }); 95 | } 96 | // 设置属性 97 | fieldWrapper.setProperty(property); 98 | fxFieldWrapperMap.put(field.getName(), fieldWrapper); 99 | } 100 | } 101 | fxEntityProxy.setFXFieldWrapperMap(fxFieldWrapperMap); 102 | } 103 | 104 | /** 105 | * @param entityObject 106 | * @param field 107 | * @return 108 | * @throws IllegalAccessException 109 | * @Description 某一属性中有初始值时 110 | */ 111 | private static Property getFieldProperty(Object entityObject, Field field) throws IllegalAccessException { 112 | Class type = field.getType(); 113 | Object value = field.get(entityObject); 114 | Property property = null; 115 | 116 | if (Boolean.class.equals(type) || boolean.class.equals(type)) { 117 | property = new SimpleBooleanProperty((Boolean) value); 118 | } else if (Double.class.equals(type) || double.class.equals(type)) { 119 | property = new SimpleDoubleProperty((Double) value); 120 | } else if (Float.class.equals(type) || float.class.equals(type)) { 121 | property = new SimpleFloatProperty((Float) value); 122 | } else if (Integer.class.equals(type) || int.class.equals(type)) { 123 | property = new SimpleIntegerProperty((Integer) value); 124 | } else if (Long.class.equals(type) || long.class.equals(type)) { 125 | property = new SimpleLongProperty((Long) value); 126 | } else if (String.class.equals(type)) { 127 | property = new SimpleStringProperty((String) value); 128 | } else if (List.class.isAssignableFrom(type)) { 129 | property = new SimpleListProperty(FXCollections.observableList((List) value)); 130 | } else if (Object.class.isAssignableFrom(type)) { 131 | property = new SimpleObjectProperty(value); 132 | } 133 | return property; 134 | } 135 | 136 | /** 137 | * @param field 138 | * @return 139 | * @throws IllegalAccessException 140 | * @Description 某一属性中无初始值 141 | */ 142 | private static Property getFieldDefaultProperty(Field field) throws IllegalAccessException { 143 | Class type = field.getType(); 144 | Property property = null; 145 | 146 | if (Boolean.class.equals(type) || boolean.class.equals(type)) { 147 | property = new SimpleBooleanProperty(); 148 | } else if (Double.class.equals(type) || double.class.equals(type)) { 149 | property = new SimpleDoubleProperty(); 150 | } else if (Float.class.equals(type) || float.class.equals(type)) { 151 | property = new SimpleFloatProperty(); 152 | } else if (Integer.class.equals(type) || int.class.equals(type)) { 153 | property = new SimpleIntegerProperty(); 154 | } else if (Long.class.equals(type) || long.class.equals(type)) { 155 | property = new SimpleLongProperty(); 156 | } else if (String.class.equals(type)) { 157 | property = new SimpleStringProperty(); 158 | } else if (List.class.isAssignableFrom(type)) { 159 | property = new SimpleListProperty(); 160 | } else if (Object.class.isAssignableFrom(type)) { 161 | property = new SimpleObjectProperty(); 162 | } 163 | return property; 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/function/DragWindowHandlerImpl.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.function; 2 | 3 | import javafx.event.EventHandler; 4 | import javafx.scene.Cursor; 5 | import javafx.scene.input.MouseEvent; 6 | import javafx.scene.layout.Pane; 7 | import javafx.stage.Stage; 8 | 9 | /** 10 | * @author jack 11 | * @version 1.0 12 | * @date 2019/6/30 10:11 13 | * @since JavaFX2.0 JDK1.8 14 | */ 15 | public class DragWindowHandlerImpl implements EventHandler { 16 | //参考 17 | private Stage stage; //primaryStage为start方法头中的Stage 18 | private double oldStageX; 19 | private double oldStageY; 20 | private double oldScreenX; 21 | private double oldScreenY; 22 | final int RESIZE_WIDTH = 5;// 判定是否为调整窗口状态的范围与边界距离 23 | private double MIN_WIDTH = 300;// 窗口最小宽度 24 | private double MIN_HEIGHT = 250;// 窗口最小高度 25 | boolean isRight;// 是否处于右边界调整窗口状态 26 | boolean isBottomRight;// 是否处于右下角调整窗口状态 27 | boolean isBottom;// 是否处于下边界调整窗口状态 28 | private Pane pane; 29 | private boolean resizable; //是否拉伸 30 | private boolean draggable; //是否拖拽 31 | 32 | 33 | public DragWindowHandlerImpl(Stage primaryStage, Pane pane, boolean draggable, boolean resizable) { //构造器 34 | this.stage = primaryStage; 35 | this.pane = pane; 36 | this.draggable = draggable; 37 | this.resizable = resizable; 38 | } 39 | 40 | public DragWindowHandlerImpl(Stage stage, double MIN_WIDTH, double MIN_HEIGHT, Pane pane, boolean draggable, boolean resizable) { 41 | this.stage = stage; 42 | this.MIN_WIDTH = MIN_WIDTH; 43 | this.MIN_HEIGHT = MIN_HEIGHT; 44 | this.pane = pane; 45 | this.draggable = draggable; 46 | this.resizable = resizable; 47 | } 48 | 49 | @Override 50 | public void handle(MouseEvent e) { 51 | 52 | if (e.getEventType() == MouseEvent.MOUSE_PRESSED) { //鼠标按下的事件 53 | //鼠标按下时记录坐标 54 | this.oldStageX = this.stage.getX(); 55 | this.oldStageY = this.stage.getY(); 56 | this.oldScreenX = e.getScreenX(); 57 | this.oldScreenY = e.getScreenY(); 58 | } else if (e.getEventType() == MouseEvent.MOUSE_DRAGGED) { //鼠标拖动的事件 59 | double nextX = stage.getX(); 60 | double nextY = stage.getY(); 61 | double nextWidth = stage.getWidth(); 62 | double nextHeight = stage.getHeight(); 63 | 64 | double x = e.getSceneX(); 65 | double y = e.getSceneY(); 66 | // 保存窗口改变后的x、y坐标和宽度、高度,用于预判是否会小于最小宽度、最小高度 67 | if (isRight || isBottomRight) {// 所有右边调整窗口状态 68 | nextWidth = x; 69 | } 70 | if (isBottomRight || isBottom) {// 所有下边调整窗口状态 71 | nextHeight = y; 72 | } 73 | if (nextWidth <= MIN_WIDTH) {// 如果窗口改变后的宽度小于最小宽度,则宽度调整到最小宽度 74 | nextWidth = MIN_WIDTH; 75 | } 76 | if (nextHeight <= MIN_HEIGHT) {// 如果窗口改变后的高度小于最小高度,则高度调整到最小高度 77 | nextHeight = MIN_HEIGHT; 78 | } 79 | 80 | // 最后统一改变窗口的x、y坐标和宽度、高度,可以防止刷新频繁出现的屏闪情况 81 | if (draggable) { 82 | if (isBottom || isBottomRight || isRight) { 83 | stage.setX(nextX); 84 | stage.setY(nextY); 85 | } else { 86 | this.stage.setX(e.getScreenX() - this.oldScreenX + this.oldStageX); 87 | this.stage.setY(e.getScreenY() - this.oldScreenY + this.oldStageY); 88 | } 89 | } 90 | if (resizable) { 91 | stage.setWidth(nextWidth); 92 | stage.setHeight(nextHeight); 93 | } 94 | } else if (e.getEventType() == MouseEvent.MOUSE_MOVED) { //鼠标移动 95 | e.consume(); 96 | double x = e.getSceneX(); 97 | double y = e.getSceneY(); 98 | double width = stage.getWidth(); 99 | double height = stage.getHeight(); 100 | Cursor cursorType = Cursor.DEFAULT;// 鼠标光标初始为默认类型,若未进入调整窗口状态,保持默认类型 101 | // 先将所有调整窗口状态重置 102 | isRight = isBottomRight = isBottom = false; 103 | 104 | if (resizable) { 105 | if (y >= height - RESIZE_WIDTH) { 106 | if (x <= RESIZE_WIDTH) {// 左下角调整窗口状态 107 | 108 | } else if (x >= width - RESIZE_WIDTH) {// 右下角调整窗口状态 109 | isBottomRight = true; 110 | cursorType = Cursor.SE_RESIZE; 111 | } else {// 下边界调整窗口状态 112 | isBottom = true; 113 | cursorType = Cursor.S_RESIZE; 114 | } 115 | } else if (x >= width - RESIZE_WIDTH) {// 右边界调整窗口状态 116 | isRight = true; 117 | cursorType = Cursor.E_RESIZE; 118 | } 119 | // 最后改变鼠标光标 120 | pane.setCursor(cursorType); 121 | } 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/function/Draggale.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.function; 2 | 3 | /** 4 | * @author jack 5 | * @version 1.0 6 | * @date 2019/7/27 1:54 7 | * @since JavaFX2.0 JDK1.8 8 | */ 9 | public interface Draggale { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/function/FXWindowParser.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.function; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXWindow; 4 | import cn.edu.scau.biubiusuisui.entity.FXBaseController; 5 | import cn.edu.scau.biubiusuisui.exception.ProtocolNotSupport; 6 | import cn.edu.scau.biubiusuisui.log.FXPlusLoggerFactory; 7 | import cn.edu.scau.biubiusuisui.log.IFXPlusLogger; 8 | import cn.edu.scau.biubiusuisui.utils.FileUtil; 9 | import cn.edu.scau.biubiusuisui.utils.StringUtil; 10 | import javafx.event.EventHandler; 11 | import javafx.scene.image.Image; 12 | import javafx.stage.Stage; 13 | 14 | import java.io.File; 15 | import java.net.URL; 16 | 17 | /** 18 | * @author jack 19 | * @version 1.0 20 | * @date 2019/6/30 10:40 21 | * @description 解析@FXWindow 22 | * @since JavaFX2.0 JDK1.8 23 | */ 24 | public class FXWindowParser { 25 | private static IFXPlusLogger logger = FXPlusLoggerFactory.getLogger(FXWindowParser.class); 26 | 27 | public void parse(Stage stage, FXBaseController fxControllerProxy, FXWindow fxWindow) { 28 | logger.info("parsing @FXWindow of class: " + fxControllerProxy.getName()); 29 | // 处理 title 30 | stage.setTitle(fxWindow.title()); 31 | 32 | // 处理 icon 33 | if (!"".equals(fxWindow.icon())) { 34 | try { 35 | URL iconUrl = new FileUtil().getFilePathFromResources(fxWindow.icon()); 36 | if (iconUrl != null) { 37 | if (new File(StringUtil.getRootPath(iconUrl)).exists()) { 38 | stage.getIcons().add(new Image(fxWindow.icon())); 39 | } else { 40 | logger.warn("the icon file has not existed"); 41 | } 42 | } else { 43 | logger.warn("the icon file has not existed"); 44 | } 45 | } catch (ProtocolNotSupport protocolNotSupport) { 46 | logger.error(protocolNotSupport.getMessage(), protocolNotSupport); 47 | protocolNotSupport.printStackTrace(); 48 | } 49 | } 50 | 51 | // fxWindow的resizable默认为false 52 | if (fxWindow.resizable()) { 53 | stage.setResizable(true); 54 | } 55 | 56 | // 处理draggable和resizable 57 | if (fxWindow.draggable() || fxWindow.resizable()) { 58 | EventHandler dragWindowHandler = new DragWindowHandlerImpl(stage, fxWindow.minWidth(), fxWindow.minHeight(), fxControllerProxy, fxWindow.draggable(), fxWindow.resizable()); 59 | fxControllerProxy.setOnMousePressed(dragWindowHandler); 60 | fxControllerProxy.setOnMouseDragged(dragWindowHandler); 61 | fxControllerProxy.setOnMouseMoved(dragWindowHandler); 62 | } 63 | // 处理style 64 | stage.initStyle(fxWindow.style()); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/log/FXPlusLogger.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.log; 2 | 3 | 4 | import org.apache.log4j.Level; 5 | import org.apache.log4j.Logger; 6 | 7 | /** 8 | * @author suisui 9 | * @version 1.2 10 | * @description JavaPlus的日志类 11 | * @date 2020/5/1 10:55 12 | * @since JavaFX2.0 JDK1.8 13 | */ 14 | public class FXPlusLogger implements IFXPlusLogger { 15 | private Logger logger; 16 | private String FQCN; 17 | 18 | public FXPlusLogger(Logger logger) { 19 | this.FQCN = FXPlusLogger.class.getName(); 20 | this.logger = logger; 21 | } 22 | 23 | public FXPlusLogger(String fqcn, Logger logger) { 24 | this.FQCN = fqcn; 25 | this.logger = logger; 26 | } 27 | 28 | @Override 29 | public void debug(Object message) { 30 | logger.log(FQCN, Level.DEBUG, message, null); 31 | } 32 | 33 | @Override 34 | public void debug(Object message, Throwable t) { 35 | logger.log(FQCN, Level.DEBUG, message, t); 36 | } 37 | 38 | @Override 39 | public void info(Object message) { 40 | logger.log(FQCN, Level.INFO, message, null); 41 | } 42 | 43 | @Override 44 | public void info(Object message, Throwable t) { 45 | logger.log(FQCN, Level.INFO, message, t); 46 | } 47 | 48 | @Override 49 | public void warn(Object message) { 50 | logger.log(FQCN, Level.WARN, message, null); 51 | } 52 | 53 | @Override 54 | public void warn(Object message, Throwable t) { 55 | logger.log(FQCN, Level.WARN, message, t); 56 | } 57 | 58 | @Override 59 | public void error(Object message) { 60 | logger.log(FQCN, Level.ERROR, message, null); 61 | } 62 | 63 | @Override 64 | public void error(Object message, Throwable t) { 65 | logger.log(FQCN, Level.ERROR, message, t); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/log/FXPlusLoggerContext.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.log; 2 | 3 | /** 4 | * @author suisui 5 | * @version 1.2 6 | * @description 日志类上下文 7 | * @date 2020/5/1 10:56 8 | * @since JavaFX2.0 JDK1.8 9 | */ 10 | public class FXPlusLoggerContext { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/log/FXPlusLoggerFactory.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.log; 2 | 3 | import cn.edu.scau.biubiusuisui.utils.LogUtil; 4 | import org.apache.log4j.Logger; 5 | 6 | /** 7 | * @author suisui 8 | * @version 1.2 9 | * @description 生成日志类的工厂 10 | * @date 2020/5/1 10:56 11 | * @since JavaFX2.0 JDK1.8 12 | */ 13 | public class FXPlusLoggerFactory { 14 | 15 | private FXPlusLoggerFactory() { 16 | 17 | } 18 | 19 | public static IFXPlusLogger getLogger(Class clazz) { 20 | LogUtil.initLog4jBase(); 21 | Logger logger = Logger.getLogger(clazz); 22 | return new FXPlusLogger(logger); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/log/IFXPlusLogger.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.log; 2 | 3 | 4 | import org.slf4j.Logger; 5 | 6 | /** 7 | * @author suisui 8 | * @version 1.2 9 | * @description 日志接口 10 | * @date 2020/5/1 10:54 11 | * @since JavaFX2.0 JDK1.8 12 | */ 13 | public interface IFXPlusLogger { 14 | void debug(Object message); 15 | 16 | void debug(Object message, Throwable t); 17 | 18 | void info(Object message); 19 | 20 | void info(Object message, Throwable t); 21 | 22 | void warn(Object message); 23 | 24 | void warn(Object message, Throwable t); 25 | 26 | void error(Object message); 27 | 28 | void error(Object message, Throwable t); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/messageQueue/MessageQueue.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.messageQueue; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXReceiver; 4 | import cn.edu.scau.biubiusuisui.entity.FXBaseController; 5 | import cn.edu.scau.biubiusuisui.entity.FXMethodEntity; 6 | import cn.edu.scau.biubiusuisui.log.FXPlusLoggerFactory; 7 | import cn.edu.scau.biubiusuisui.log.IFXPlusLogger; 8 | 9 | import java.lang.annotation.Annotation; 10 | import java.lang.reflect.InvocationTargetException; 11 | import java.lang.reflect.Method; 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | import java.util.Map; 15 | import java.util.concurrent.ConcurrentHashMap; 16 | 17 | /** 18 | * @author jack 19 | * @version 1.0 20 | * @date 2019/6/25 12:24 21 | * @since JavaFX2.0 JDK1.8 22 | */ 23 | 24 | public class MessageQueue { 25 | private IFXPlusLogger logger = FXPlusLoggerFactory.getLogger(MessageQueue.class); 26 | 27 | private static Map> receivers = new ConcurrentHashMap<>(); //Map<主题,订阅了主题的所有方法> 28 | 29 | private static MessageQueue messageQueue = null; 30 | 31 | private MessageQueue() { 32 | } 33 | 34 | public static synchronized MessageQueue getInstance() { 35 | if (messageQueue == null) { 36 | messageQueue = new MessageQueue(); 37 | } 38 | return messageQueue; 39 | } 40 | 41 | /** 42 | * @param fxBaseController 43 | * @param fxBaseControllerProxy 44 | * @Description 注册消费者,即FXReceiver注解的method 45 | */ 46 | public void registerConsumer(FXBaseController fxBaseController, FXBaseController fxBaseControllerProxy) { 47 | Class clazz = fxBaseController.getClass(); 48 | Method[] methods = clazz.getDeclaredMethods(); 49 | for (Method method : methods) { 50 | Annotation[] annotations = method.getDeclaredAnnotations(); 51 | for (Annotation annotation : annotations) { 52 | if (FXReceiver.class.equals(annotation.annotationType())) { 53 | logger.info("registering consumer: " + fxBaseControllerProxy.getName()); 54 | // System.out.println("FXReceiver"); 55 | FXReceiver receiver = (FXReceiver) annotation; 56 | FXMethodEntity fxMethodEntity = new FXMethodEntity(fxBaseControllerProxy, method); 57 | List fxMethodEntities = receivers.get(receiver.name()); 58 | if (fxMethodEntities == null) { 59 | fxMethodEntities = new ArrayList<>(); 60 | } 61 | fxMethodEntities.add(fxMethodEntity); 62 | receivers.put(receiver.name(), fxMethodEntities); 63 | } 64 | } 65 | } 66 | } 67 | 68 | /** 69 | * @param id 70 | * @param msg 71 | * @Description 处理消息发送,id为topic,msg为消息 72 | */ 73 | public void sendMsg(String id, Object msg) { 74 | List lists = receivers.get(id); 75 | if (lists != null) { 76 | for (FXMethodEntity fxMethodEntity : lists) { 77 | Method method = fxMethodEntity.getMethod(); 78 | method.setAccessible(true); 79 | FXBaseController fxBaseController = fxMethodEntity.getFxBaseController(); 80 | if (method.getParameterCount() == 0) { 81 | try { 82 | method.invoke(fxBaseController); 83 | } catch (IllegalAccessException e) { 84 | logger.error(e.getMessage()); 85 | e.printStackTrace(); 86 | } catch (InvocationTargetException e) { 87 | logger.error(e.getMessage()); 88 | e.printStackTrace(); 89 | } 90 | } else { 91 | try { 92 | // obj the object the underlying method is invoked from 93 | method.invoke(fxBaseController, msg); 94 | } catch (IllegalAccessException e) { 95 | logger.error(e.getMessage()); 96 | e.printStackTrace(); 97 | } catch (InvocationTargetException e) { 98 | logger.error(e.getMessage()); 99 | e.printStackTrace(); 100 | } 101 | } 102 | } 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/proxy/FXControllerProxy.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.proxy; 2 | 3 | import cn.edu.scau.biubiusuisui.annotation.FXRedirect; 4 | import cn.edu.scau.biubiusuisui.annotation.FXSender; 5 | import cn.edu.scau.biubiusuisui.entity.FXBaseController; 6 | import cn.edu.scau.biubiusuisui.messageQueue.MessageQueue; 7 | import cn.edu.scau.biubiusuisui.stage.StageManager; 8 | import net.sf.cglib.proxy.Enhancer; 9 | import net.sf.cglib.proxy.MethodInterceptor; 10 | import net.sf.cglib.proxy.MethodProxy; 11 | 12 | import java.lang.annotation.Annotation; 13 | import java.lang.reflect.Field; 14 | import java.lang.reflect.Method; 15 | 16 | /** 17 | * This proxy class intercept Methods that has special annotation such as 18 | * FXSender which is a mark for message queue 19 | * 20 | * @author jack 21 | * @version 1.0 22 | * @date 2019/6/25 2:03 23 | * @since JavaFX2.0 JDK1.8 24 | */ 25 | public class FXControllerProxy implements MethodInterceptor { 26 | 27 | 28 | FXBaseController target; 29 | 30 | 31 | public Object getInstance(FXBaseController target) { 32 | this.target = target; 33 | Enhancer enhancer = new Enhancer(); 34 | enhancer.setSuperclass(this.target.getClass()); 35 | enhancer.setCallback(this); 36 | Object proxy = enhancer.create(); 37 | // target.* -> proxy.* 38 | inject(target, proxy); 39 | return proxy; 40 | } 41 | 42 | @Override 43 | public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { 44 | Object o1 = methodProxy.invokeSuper(o, objects); //获取该方法运行后的结果 45 | Annotation[] annotations = method.getDeclaredAnnotations(); 46 | 47 | for (Annotation annotation : annotations) { 48 | if (FXSender.class.equals(annotation.annotationType())) { // 拦截是否发送消息函数 49 | FXSender fxSender = (FXSender) annotation; 50 | // System.out.println("FXSender"); 51 | String name = target.getName() + ":"; 52 | // System.out.println("FXControllerProxy:" + name); 53 | if ("".equals(fxSender.name())) { 54 | name += method.getName(); 55 | } else { 56 | name += fxSender.name(); 57 | } 58 | MessageQueue.getInstance().sendMsg(name, o1); 59 | } 60 | if (FXRedirect.class.equals((annotation.annotationType()))) { //拦截是否重定向函数 61 | FXRedirect fxRedirect = (FXRedirect) annotation; 62 | if (fxRedirect.close()) { //关闭原窗口 63 | StageManager.getInstance().closeStage(target.getName()); 64 | } 65 | StageManager.getInstance().redirectTo(o1); 66 | } 67 | } 68 | return o1; 69 | } 70 | 71 | private void inject(Object target, Object proxy) { 72 | Class clazz = target.getClass(); 73 | Field[] fields = clazz.getDeclaredFields(); 74 | for (Field field : fields) { 75 | field.setAccessible(true); 76 | try { 77 | Object value = field.get(target); 78 | field.set(proxy, value); 79 | } catch (IllegalAccessException e) { 80 | e.printStackTrace(); 81 | } 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/proxy/FXEntityProxy.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.proxy; 2 | 3 | import cn.edu.scau.biubiusuisui.entity.FXFieldWrapper; 4 | import cn.edu.scau.biubiusuisui.utils.StringUtil; 5 | import javafx.beans.property.*; 6 | import net.sf.cglib.proxy.Enhancer; 7 | import net.sf.cglib.proxy.MethodInterceptor; 8 | import net.sf.cglib.proxy.MethodProxy; 9 | 10 | import java.lang.reflect.Method; 11 | import java.util.Map; 12 | 13 | /** 14 | * @author jack 15 | * @version 1.0 16 | * @date 2019/6/27 18:47 17 | * @since JavaFX2.0 JDK1.8 18 | */ 19 | public class FXEntityProxy implements MethodInterceptor { 20 | 21 | Object target; 22 | private Map fxFieldWrapperMap; 23 | 24 | /** 25 | * @param target 26 | * @return 27 | * @Desciption 通过getInstance获取代理对象 28 | */ 29 | public Object getInstance(Object target) { 30 | this.target = target; 31 | Enhancer enhancer = new Enhancer(); 32 | enhancer.setSuperclass(this.target.getClass()); 33 | enhancer.setCallback(this); 34 | return enhancer.create(); 35 | } 36 | 37 | /** 38 | * intercept get and set method and 39 | * 40 | * @param proxy cglib生成的代理对象 41 | * @param method 被代理对象的方法 42 | * @param args 拦截的方法的入参 43 | * @param methodProxy 拦截方法的代理方法 44 | * @return 45 | * @throws Throwable 46 | * @Descripton 拦截getter, setter, del, cls, add方法 47 | */ 48 | 49 | @Override 50 | public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { 51 | Object revokeResult = methodProxy.invokeSuper(proxy, args); //获取该方法运行后的结果 52 | String methodName = method.getName(); 53 | String fieldName = null; 54 | if (methodName.length() >= 3) { 55 | fieldName = StringUtil.toInstanceName(methodName.substring(3)); // 该method有可能是getter和setter方法,进行处理 56 | } else { 57 | return revokeResult; 58 | } 59 | FXFieldWrapper fxFieldWrapper = fxFieldWrapperMap.get(fieldName); 60 | Property property = getPropertyByFieldName(fieldName); 61 | if (fxFieldWrapper == null || property == null) { //非属性的getter或setter 62 | return revokeResult; 63 | } 64 | Class type = fxFieldWrapper.getType(); 65 | if (methodName.startsWith("set")) { 66 | if (Boolean.class.equals(type) || boolean.class.equals(type)) { 67 | ((SimpleBooleanProperty) property).set((Boolean) args[0]); 68 | } else if (Double.class.equals(type) || double.class.equals(type)) { 69 | ((SimpleDoubleProperty) property).set((Double) args[0]); 70 | } else if (Float.class.equals(type) || float.class.equals(type)) { 71 | ((SimpleFloatProperty) property).set((Float) args[0]); 72 | } else if (Integer.class.equals(type) || int.class.equals(type)) { 73 | ((SimpleIntegerProperty) property).set((Integer) args[0]); 74 | } else if (Long.class.equals(type) || long.class.equals(type)) { 75 | ((SimpleLongProperty) property).set((Long) args[0]); 76 | } else if (String.class.equals(type)) { 77 | ((SimpleStringProperty) property).set((String) args[0]); 78 | } 79 | } else if (methodName.startsWith("add")) { 80 | ((SimpleListProperty) (property)).add(args[0]); 81 | } else if (methodName.startsWith("del")) { 82 | ((SimpleListProperty) (property)).remove(args[0]); 83 | } else if (methodName.startsWith("cls")) { 84 | ((SimpleListProperty) (property)).clear(); 85 | } 86 | return revokeResult; 87 | } 88 | 89 | public Object getTarget() { 90 | return target; 91 | } 92 | 93 | public void setTarget(Object target) { 94 | this.target = target; 95 | } 96 | 97 | public Property getPropertyByFieldName(String name) { 98 | if (fxFieldWrapperMap.get(name) == null) { 99 | return null; 100 | } 101 | return fxFieldWrapperMap.get(name).getProperty(); 102 | } 103 | 104 | public Map getFXFieldWrapperMap() { 105 | return fxFieldWrapperMap; 106 | } 107 | 108 | public void setFXFieldWrapperMap(Map fxFieldWrapperMap) { 109 | this.fxFieldWrapperMap = fxFieldWrapperMap; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/stage/StageManager.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.stage; 2 | 3 | import cn.edu.scau.biubiusuisui.entity.FXBaseController; 4 | import cn.edu.scau.biubiusuisui.entity.FXPlusContext; 5 | import cn.edu.scau.biubiusuisui.entity.FXRedirectParam; 6 | import cn.edu.scau.biubiusuisui.exception.InvalidURLException; 7 | import cn.edu.scau.biubiusuisui.log.FXPlusLoggerFactory; 8 | import cn.edu.scau.biubiusuisui.log.IFXPlusLogger; 9 | 10 | import java.util.ArrayDeque; 11 | import java.util.List; 12 | import java.util.Map; 13 | import java.util.concurrent.ConcurrentHashMap; 14 | 15 | /** 16 | * @author suisui 17 | * @version 1.1 18 | * @description 舞台管理器 19 | * @date 2019/12/3 15:43 20 | * @since JavaFX2.0 JDK1.8 21 | */ 22 | public class StageManager { 23 | private static IFXPlusLogger logger = FXPlusLoggerFactory.getLogger(StageManager.class); 24 | 25 | private static StageManager stageManager = null; 26 | private static Map initWindows = new ConcurrentHashMap<>(); 27 | private static Map windowClazz = new ConcurrentHashMap<>(); 28 | /** 29 | * @author yangsuiyu 30 | * @description 1.2新增属性 31 | */ 32 | private static ArrayDeque windowsStack = new ArrayDeque<>(); 33 | 34 | private StageManager() { 35 | 36 | } 37 | 38 | /** 39 | * 单例 40 | * 41 | * @return 42 | */ 43 | public static synchronized StageManager getInstance() { 44 | if (stageManager == null) { 45 | stageManager = new StageManager(); 46 | } 47 | return stageManager; 48 | } 49 | 50 | /** 51 | * 注册FXWindow注解的Controller 52 | * 53 | * @param clazz 54 | * @param fxBaseControllerProxy 55 | */ 56 | public void registerWindow(Class clazz, FXBaseController fxBaseControllerProxy) { 57 | fxBaseControllerProxy.getClass().getDeclaredAnnotations(); 58 | initWindows.put(fxBaseControllerProxy.getName(), fxBaseControllerProxy); 59 | windowClazz.put(fxBaseControllerProxy.getName(), clazz); 60 | } 61 | 62 | /** 63 | * 关闭窗口 64 | * 65 | * @param controllerName 66 | */ 67 | public void closeStage(String controllerName) { 68 | if (initWindows.get(controllerName) != null) { 69 | initWindows.get(controllerName).closeStage(); 70 | } 71 | } 72 | 73 | /** 74 | * @param redirectParams 75 | * @Description 跳转 76 | */ 77 | public void redirectTo(Object redirectParams) { 78 | FXRedirectParam fxRedirectParam = null; 79 | if (redirectParams instanceof String) { 80 | if (((String) redirectParams).contains("?")) { //有参数,query return "SuccessController?name=ss&psw=111" 81 | try { 82 | fxRedirectParam = getQueryParamsFromURL((String) redirectParams); 83 | } catch (InvalidURLException e) { 84 | logger.error(e.getMessage()); 85 | e.printStackTrace(); 86 | } 87 | } else { //无参数 return "SuccessController" 88 | fxRedirectParam = new FXRedirectParam((String) redirectParams); 89 | } 90 | } else if (redirectParams instanceof FXRedirectParam) { // return FXRedirectParam 91 | fxRedirectParam = (FXRedirectParam) redirectParams; 92 | } 93 | redirectWithParams(fxRedirectParam); 94 | } 95 | 96 | /** 97 | * @param fxRedirectParam 98 | * @Description 携带参数跳转 99 | */ 100 | private void redirectWithParams(FXRedirectParam fxRedirectParam) { 101 | if (fxRedirectParam != null) { 102 | String toControllerStr = fxRedirectParam.getToController(); 103 | FXBaseController toController = initWindows.get(toControllerStr); 104 | if (toController != null) { 105 | List controllers = FXPlusContext.getControllers(toController.getName()); 106 | // if (controllers.size() > 0) { 107 | // FXBaseController newController = controllers.get(controllers.size() - 1); 108 | // toController = FXControllerFactory.getFXController(newController.getClass(), toControllerStr); 109 | //// registerWindow(, toController); 110 | // } 111 | logger.debug("redirecting to " + toController.getName()); 112 | toController.setParam(fxRedirectParam.getParams()); 113 | toController.setQuery(fxRedirectParam.getQueryMap()); 114 | toController.showStage(); 115 | } 116 | } 117 | } 118 | 119 | /** 120 | * RedirectController?num=10&name=suisui -> Map:{"num","10"},{"name","suisui"} 121 | * 122 | * @param url 123 | * @return 124 | */ 125 | private FXRedirectParam getQueryParamsFromURL(String url) throws InvalidURLException { 126 | String[] items = url.split("\\?"); 127 | if (items.length != 2) { 128 | throw new InvalidURLException(); 129 | } 130 | String leftBase = items[0]; 131 | String paramsStr = items[1]; 132 | String[] paramsKV = paramsStr.split("&"); 133 | 134 | FXRedirectParam fxRedirectParam = new FXRedirectParam(leftBase); 135 | for (int i = 0; i < paramsKV.length; i++) { 136 | String params[] = paramsKV[i].split("="); 137 | if (params.length != 2) { 138 | throw new InvalidURLException(); 139 | } else { 140 | fxRedirectParam.addQuery(params[0], params[1]); 141 | } 142 | } 143 | return fxRedirectParam; 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/utils/BeanUtil.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.utils; 2 | 3 | import cn.edu.scau.biubiusuisui.entity.FXPlusContext; 4 | import cn.edu.scau.biubiusuisui.proxy.FXEntityProxy; 5 | import javafx.beans.property.Property; 6 | 7 | /** 8 | * @author jack 9 | * @version 1.0 10 | * @Date:2019/7/28 1:52 11 | * @Description: 12 | * @since JavaFX2.0 JDK1.8 13 | */ 14 | public class BeanUtil { 15 | public static Property getPropertyByName(Object entity, String fieldName) { 16 | FXEntityProxy fxEntityProxy = FXPlusContext.getProxyByBeanObject(entity); 17 | if (fxEntityProxy == null) { 18 | return null; 19 | } 20 | return fxEntityProxy.getFXFieldWrapperMap().get(fieldName).getProperty(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/utils/ClassUtil.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.utils; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.lang.annotation.Annotation; 6 | import java.lang.reflect.Field; 7 | import java.net.URL; 8 | import java.util.*; 9 | import java.util.jar.JarEntry; 10 | import java.util.jar.JarFile; 11 | 12 | /** 13 | * @author jack 14 | * @version 1.0 15 | * @date 2019/6/25 5:20 16 | * @since JavaFX2.0 JDK1.8 17 | */ 18 | public class ClassUtil { 19 | private ClassLoader classLoader; 20 | 21 | public ClassUtil() { 22 | classLoader = getClass().getClassLoader(); 23 | } 24 | 25 | private List getAllFXControllerClassName(String base, List nameList) { 26 | String splashPath = StringUtil.dotToSplash(base); 27 | URL url = classLoader.getResource(splashPath); 28 | String filePath = StringUtil.getRootPath(url); 29 | List names = null; 30 | if (filePath.endsWith("jar")) { 31 | nameList = readFromJarDirectory(filePath, base); 32 | } else { 33 | names = readFromDirectory(filePath); 34 | for (String name : names) { 35 | if (isClassFile(name)) { 36 | nameList.add(toFullyQualifiedName(name, base)); 37 | } else if (isDirectory(name)) { 38 | nameList = getAllFXControllerClassName(base + "." + name, nameList); 39 | } 40 | } 41 | } 42 | return nameList; 43 | } 44 | 45 | public List scanAllClassName(String base) { 46 | return getAllFXControllerClassName(base, new LinkedList<>()); 47 | } 48 | 49 | private static String toFullyQualifiedName(String shortName, String basePackage) { 50 | StringBuilder sb = new StringBuilder(basePackage); 51 | sb.append('.'); 52 | sb.append(StringUtil.trimExtension(shortName)); 53 | return sb.toString(); 54 | } 55 | 56 | private static boolean isClassFile(String name) { 57 | return name.endsWith(".class"); 58 | } 59 | 60 | private static boolean isDirectory(String name) { 61 | return !name.contains("."); 62 | } 63 | 64 | private static List readFromDirectory(String path) { 65 | if (path == null) return null; 66 | return readFromFileDirectory(path); 67 | } 68 | 69 | private static List readFromJarDirectory(String path, String packageName) { 70 | JarFile jarFile = null; 71 | try { 72 | jarFile = new JarFile(path); 73 | } catch (IOException e) { 74 | e.printStackTrace(); 75 | } 76 | Enumeration entrys = jarFile.entries(); 77 | List classNames = new ArrayList<>(); 78 | while (entrys.hasMoreElements()) { 79 | JarEntry jarEntry = entrys.nextElement(); 80 | if (!jarEntry.getName().endsWith(".class")) continue; 81 | int packageNameIndex = jarEntry.getName().indexOf("/"); 82 | if ("".equals(packageName)) { 83 | classNames.add(jarEntry.getName()); 84 | } else { 85 | if (packageNameIndex == -1) continue; 86 | String baseName = jarEntry.getName().substring(0, packageNameIndex); 87 | if (baseName.equals(packageName)) { 88 | classNames.add(StringUtil.trimExtension(jarEntry.getName()).replaceAll("/", ".")); 89 | } 90 | } 91 | } 92 | return classNames; 93 | } 94 | 95 | private static List readFromFileDirectory(String path) { 96 | File file = new File(path); 97 | String[] names = file.list(); 98 | if (null == names) { 99 | return null; 100 | } else { 101 | return Arrays.asList(names); 102 | } 103 | } 104 | 105 | 106 | public static boolean hasDeclaredAnnotation(Class clazz, Class annotation) { 107 | if (annotation == null) { 108 | return false; 109 | } 110 | if (hasAnnotationInList(annotation, clazz.getDeclaredAnnotations())) return true; 111 | return false; 112 | } 113 | 114 | public static boolean hasAnnotation(Class clazz, Class annotation) { 115 | if (annotation == null) { 116 | return false; 117 | } 118 | if (hasAnnotationInList(annotation, clazz.getAnnotations())) return true; 119 | return false; 120 | } 121 | 122 | public static boolean hasAnnotationInList(Class annotation, Annotation[] annotations2) { 123 | if (getAnnotationInList(annotation, annotations2) == null) { 124 | return false; 125 | } else { 126 | return true; 127 | } 128 | } 129 | 130 | public static Annotation getAnnotationInList(Class annotation, Annotation[] annotations) { 131 | if (annotations == null || annotation == null) { 132 | return null; 133 | } 134 | for (Annotation annotation1 : annotations) { 135 | if (annotation1.annotationType().equals(annotation)) { 136 | return annotation1; 137 | } 138 | } 139 | return null; 140 | } 141 | 142 | public static void copyField(Object target, Object base) { 143 | Class clazz = base.getClass(); 144 | Class targetClass = target.getClass(); 145 | Field[] fields = clazz.getDeclaredFields(); 146 | for (Field field : fields) { 147 | field.setAccessible(true); 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/utils/FileUtil.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.utils; 2 | 3 | import cn.edu.scau.biubiusuisui.exception.ProtocolNotSupport; 4 | import cn.edu.scau.biubiusuisui.log.FXPlusLoggerFactory; 5 | import cn.edu.scau.biubiusuisui.log.IFXPlusLogger; 6 | 7 | import java.io.*; 8 | import java.net.URL; 9 | 10 | /** 11 | * @author jack 12 | * @version 1.0 13 | * @date 2019/6/25 7:01 14 | * @since JavaFX2.0 JDK1.8 15 | */ 16 | public class FileUtil { 17 | private static IFXPlusLogger logger = FXPlusLoggerFactory.getLogger(FileUtil.class); 18 | 19 | /** 20 | * @param filePath 21 | * @return 22 | * @throws ProtocolNotSupport 23 | * @decription 从resources文件夹中读取File 24 | * 输出如: file:/Users/suisui/workspace/Idea/JavaFX-Plus/target/classes/image/icon.png 25 | * @version 1.0 26 | */ 27 | public URL getFilePathFromResources(String filePath) throws ProtocolNotSupport { 28 | return FileUtil.class.getClassLoader().getResource(filePath); 29 | } 30 | 31 | /** 32 | * @param filePath 33 | * @return 34 | * @description 读取resources文件夹下的file,相对于resources的文件路径,如 resources/config.conf 则只需 config.conf 35 | */ 36 | public static String readFileFromResources(String filePath) { 37 | String path = StringUtil.getRootPath(FileUtil.class.getClassLoader().getResource(filePath)); 38 | return readFile(path); 39 | } 40 | 41 | /** 42 | * @param filePath 绝对路径或相对路径 43 | * @return 44 | * @description 读取文件 45 | */ 46 | public static String readFile(String filePath) { 47 | StringBuffer content = new StringBuffer(); 48 | try (FileReader reader = new FileReader(filePath); 49 | BufferedReader br = new BufferedReader(reader) // 建立一个对象,它把文件内容转成计算机能读懂的语言 50 | ) { 51 | String temp; 52 | while ((temp = br.readLine()) != null) { 53 | // 一次读入一行数据 54 | content.append(temp + "\r\n"); 55 | } 56 | } catch (IOException e) { 57 | logger.error(e.getMessage()); 58 | e.printStackTrace(); 59 | } 60 | return content.toString(); 61 | } 62 | 63 | /** 64 | * @param filePath 65 | * @param content 66 | * @description 写文件 67 | */ 68 | public static void writeFile(String filePath, String content) { 69 | try { 70 | File writeName = new File(filePath); // 相对路径,如果没有则要建立一个新的output.txt文件 71 | writeName.createNewFile(); // 创建新文件,有同名的文件的话直接覆盖 72 | try (FileWriter writer = new FileWriter(writeName); 73 | BufferedWriter out = new BufferedWriter(writer) 74 | ) { 75 | out.write(content); 76 | out.flush(); // 把缓存区内容压入文件 77 | } 78 | } catch (IOException e) { 79 | logger.error(e.getMessage()); 80 | e.printStackTrace(); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/utils/LogUtil.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.utils; 2 | 3 | 4 | import cn.edu.scau.biubiusuisui.log.FXPlusLogger; 5 | import cn.edu.scau.biubiusuisui.log.IFXPlusLogger; 6 | import org.apache.log4j.Logger; 7 | 8 | /** 9 | * @author suisui 10 | * @version 1.2 11 | * @description 日志工具类 12 | * @date 2020/5/1 10:54 13 | * @since JavaFX2.0 JDK1.8 14 | */ 15 | public class LogUtil { 16 | private static final String FQCN = LogUtil.class.getName(); 17 | private static IFXPlusLogger logger; 18 | 19 | static { 20 | initLog4jBase(); 21 | logger = new FXPlusLogger(FQCN, Logger.getLogger(LogUtil.class)); 22 | } 23 | 24 | public static void initLog4jBase() { 25 | if (System.getProperty("log.base") == null) { 26 | // 默认是当前目录下 27 | String projectPath = PathUtil.getCurrentPath(); 28 | initLog4jBase(projectPath); 29 | } 30 | } 31 | 32 | public static void initLog4jBase(String base) { 33 | System.setProperty("log.base", base); 34 | } 35 | 36 | public static void debug(Object message) { 37 | logger.debug(message); 38 | } 39 | 40 | public static void debug(Object message, Throwable t) { 41 | logger.debug(message, t); 42 | } 43 | 44 | public static void info(Object message) { 45 | logger.info(message); 46 | } 47 | 48 | public static void info(Object message, Throwable t) { 49 | logger.debug(message, t); 50 | } 51 | 52 | public static void warn(Object message) { 53 | logger.warn(message); 54 | } 55 | 56 | public static void warn(Object message, Throwable t) { 57 | logger.warn(message, t); 58 | } 59 | 60 | public static void error(Object message) { 61 | logger.error(message); 62 | } 63 | 64 | public static void error(Object message, Throwable t) { 65 | logger.error(message, t); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/utils/PathUtil.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.utils; 2 | 3 | /** 4 | * @author suisui 5 | * @version 1.2 6 | * @description 路径工具类 7 | * @date 2020/5/2 14:43 8 | * @since JDK1.8 9 | */ 10 | public class PathUtil { 11 | public static String getCurrentPath() { 12 | return System.getProperty("user.dir"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/utils/ResourceBundleUtil.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.utils; 2 | 3 | import cn.edu.scau.biubiusuisui.entity.FXPlusLocale; 4 | import cn.edu.scau.biubiusuisui.exception.ProtocolNotSupport; 5 | import cn.edu.scau.biubiusuisui.log.FXPlusLoggerFactory; 6 | import cn.edu.scau.biubiusuisui.log.IFXPlusLogger; 7 | 8 | import java.io.File; 9 | import java.util.Locale; 10 | import java.util.MissingResourceException; 11 | import java.util.ResourceBundle; 12 | 13 | /** 14 | * @author suisui 15 | * @version 1.2 16 | * @description 语言国际化工具类 17 | * @date 2020/5/1 11:15 18 | * @since JavaFX2.0 JDK1.8 19 | */ 20 | public class ResourceBundleUtil { 21 | private static final IFXPlusLogger logger = FXPlusLoggerFactory.getLogger(ResourceBundleUtil.class); 22 | 23 | /** 24 | * @param baseName 25 | * @param fxPlusLocale 26 | * @return 27 | * @description 获取Java的ResourceBundle 28 | */ 29 | public static ResourceBundle getResourceBundle(String baseName, FXPlusLocale fxPlusLocale) { 30 | baseName = StringUtil.trimExtension(baseName); 31 | baseName = StringUtil.splashToDot(baseName); 32 | Locale locale = ResourceBundleUtil.getLocale(fxPlusLocale); 33 | 34 | // logger.info(baseName); 35 | if (locale != null) { 36 | return ResourceBundle.getBundle(baseName, locale); 37 | } 38 | return null; 39 | } 40 | 41 | /** 42 | * @param fxPlusLocale 43 | * @return 44 | * @description 通过FXPlusLocale枚举类型获取Locale 45 | */ 46 | private static Locale getLocale(FXPlusLocale fxPlusLocale) { 47 | switch (fxPlusLocale) { 48 | case SIMPLIFIED_CHINESE: 49 | return Locale.SIMPLIFIED_CHINESE; 50 | case FRANCE: 51 | return Locale.FRANCE; 52 | case KOREAN: 53 | return Locale.KOREAN; 54 | case ENGLISH: 55 | return Locale.UK; 56 | case GERMANY: 57 | return Locale.GERMANY; 58 | case ITALIAN: 59 | return Locale.ITALIAN; 60 | case AMERICAN: 61 | return Locale.US; 62 | case JAPANESE: 63 | return Locale.JAPAN; 64 | case TRADITIONAL_CHINESE: 65 | return Locale.TRADITIONAL_CHINESE; 66 | default: 67 | return null; 68 | } 69 | } 70 | 71 | /** 72 | * @param key 73 | * @return 74 | * @description 通过key获取String类型的value值,失败或不存在返回空字符串 75 | */ 76 | public static String getStringValue(ResourceBundle resource, String key) { 77 | if ("".equals(key) || null == key) { 78 | return ""; 79 | } 80 | try { 81 | return resource.getString(key); 82 | } catch (MissingResourceException | ClassCastException e) { 83 | logger.error(e.getMessage()); 84 | // e.printStackTrace(); 85 | return ""; 86 | } 87 | } 88 | 89 | /** 90 | * @param key 91 | * @return 92 | * @description 通过key获取Integer类型的value值,失败或不存在返回-1 93 | */ 94 | public static Integer getIntegerValue(ResourceBundle resource, String key) { 95 | if ("".equals(key) || null == key) { 96 | return -1; 97 | } 98 | try { 99 | return Integer.valueOf(resource.getString(key)); 100 | } catch (MissingResourceException | NumberFormatException e) { 101 | logger.error(e.getMessage()); 102 | // e.printStackTrace(); 103 | return -1; 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/scau/biubiusuisui/utils/StringUtil.java: -------------------------------------------------------------------------------- 1 | package cn.edu.scau.biubiusuisui.utils; 2 | 3 | import cn.edu.scau.biubiusuisui.log.FXPlusLoggerFactory; 4 | import cn.edu.scau.biubiusuisui.log.IFXPlusLogger; 5 | 6 | import java.net.URL; 7 | 8 | /** 9 | * @author jack 10 | * @author suisui 11 | * @version 1.0 12 | * @date 2019/6/25 3:46 13 | * @since JavaFX2.0 JDK1.8 14 | */ 15 | public class StringUtil { 16 | private static IFXPlusLogger logger = FXPlusLoggerFactory.getLogger(StringUtil.class); 17 | 18 | private StringUtil() { 19 | 20 | } 21 | 22 | /** 23 | * "file:/home/whf/cn/fh" -> "/home/whf/cn/fh" 24 | * "jar:file:/home/whf/foo.jar!cn/fh" -> "/home/whf/foo.jar" 25 | */ 26 | public static String getRootPath(URL url) { 27 | String fileUrl = url.getFile(); 28 | int pos = fileUrl.indexOf('!'); 29 | 30 | if (-1 == pos) { 31 | return fileUrl; 32 | } 33 | 34 | return fileUrl.substring(5, pos); 35 | } 36 | 37 | /** 38 | * "cn.fh.lightning" -> "cn/fh/lightning" 39 | * 40 | * @param name 41 | * @return 42 | */ 43 | public static String dotToSplash(String name) { 44 | return name.replaceAll("\\.", "/"); 45 | } 46 | 47 | /** 48 | * "cn/fh/lightning" -> "cn.fh.lightning" 49 | * 50 | * @param name 51 | * @return 52 | */ 53 | public static String splashToDot(String name) { 54 | 55 | return name.replaceAll("/", "\\."); 56 | } 57 | 58 | /** 59 | * "Apple.class" -> "Apple" 60 | */ 61 | public static String trimExtension(String name) { 62 | int pos = name.lastIndexOf('.'); 63 | if (-1 != pos) { 64 | return name.substring(0, pos); 65 | } 66 | 67 | return name; 68 | } 69 | 70 | /** 71 | * /application/home -> /home 72 | * 73 | * @param uri 74 | * @return 75 | */ 76 | public static String trimURI(String uri) { 77 | String trimmed = uri.substring(1); 78 | int splashIndex = trimmed.indexOf('/'); 79 | 80 | return trimmed.substring(splashIndex); 81 | } 82 | 83 | /** 84 | * MainController$receive -> MainController 85 | * 86 | * @param name 87 | * @return 88 | */ 89 | public static String getBaseClassName(String name) { 90 | int index = name.indexOf("$"); 91 | if (index == -1) { 92 | return name; 93 | } 94 | // System.out.println(name.substring(0, index)); 95 | return name.substring(0, index); 96 | } 97 | 98 | 99 | /** 100 | * Object -> object ; Student -> student 101 | * 102 | * @param name 103 | * @return 104 | */ 105 | public static String toInstanceName(String name) { 106 | String result = name.substring(0, 1).toLowerCase().concat(name.substring(1)); 107 | return result; 108 | } 109 | 110 | /** 111 | * object -> Object ; student -> Student 112 | * 113 | * @param name 114 | * @return 115 | */ 116 | public static String toClassName(String name) { 117 | String result = name.substring(0, 1).toUpperCase().concat(name.substring(1)); 118 | return result; 119 | } 120 | 121 | /** 122 | * cn/edu/scau/biubiusuisui/resources/fxml/languageDemo/languageDemo.fxml -> fxml/languageDemo/languageDemo.fxml 123 | * 124 | * @param name 125 | * @return 126 | * @description 获取相对于resources目录下的路径 127 | */ 128 | public static String getFilePathInResources(String name) { 129 | String resources = "resources"; 130 | int resIdx = name.indexOf(resources); 131 | if (resIdx == -1) { 132 | return name; 133 | } 134 | return name.substring(resIdx + resources.length() + 1); 135 | } 136 | 137 | /** 138 | * cn/edu/scau/biubiusuisui/resources/fxml/languageDemo/languageDemo.fxml -> languageDemo 139 | * 140 | * @param name 文件名 141 | * @return 142 | * @version 1.2 143 | */ 144 | public static String getFileBaseName(String name) { 145 | String result = ""; 146 | String[] tempStrs = name.split("/"); 147 | if (1 == tempStrs.length) { //只有文件名,即name: languageDemo.fxml 148 | result = StringUtil.trimExtension(name); 149 | } else { 150 | result = StringUtil.trimExtension(tempStrs[tempStrs.length - 1]); 151 | } 152 | return result; 153 | } 154 | 155 | } -------------------------------------------------------------------------------- /src/main/resources/applicationContext.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | _ ________ __ _____ _ 2 | | | | ____\ \ / / | __ \| | 3 | | | __ ___ ____ _| |__ \ V / _____ | |__) | |_ _ ___ 4 | _ | |/ _` \ \ / / _` | __| > < _____ | ___/| | | | / __| 5 | | |__| | (_| |\ V / (_| | | / . \ | | | | |_| \__ \ 6 | \____/ \__,_| \_/ \__,_|_| /_/ \_\ |_| |_|\__,_|___/ -------------------------------------------------------------------------------- /src/main/resources/fxml/Main.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 26 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/main/resources/fxml/lifeDemo/lifeMain_en.properties: -------------------------------------------------------------------------------- 1 | button.goAndClose=goto Dialog and close this window 2 | button.go=goto Dialog 3 | parentController=Parent Component -------------------------------------------------------------------------------- /src/main/resources/fxml/lifeDemo/lifeMain_zh_CN.properties: -------------------------------------------------------------------------------- 1 | button.goAndClose=\u8df3\u8f6c\u5e76\u5173\u95ed\u6b64\u7a97\u53e3 2 | button.go=\u5f39\u7a97 3 | parentController=\u7236\u7ec4\u4ef6 4 | -------------------------------------------------------------------------------- /src/main/resources/fxml/lifeDemo/subBar.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/main/resources/fxml/lifeDemo/subBar_en.properties: -------------------------------------------------------------------------------- 1 | childrenController=Children Component -------------------------------------------------------------------------------- /src/main/resources/fxml/lifeDemo/subBar_zh_CN.properties: -------------------------------------------------------------------------------- 1 | childrenController=子组件 -------------------------------------------------------------------------------- /src/main/resources/fxml/listDemo/listDemo.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |