そしおSpringもJavaFXに来たす

良い時間、ハブロフスク



私のような型を䜜るのず同じ恋人があなたの䞭にいるこずを願っおいたす。

事実、私はい぀もフレンドリヌなむンタヌフェヌスに取り組んできたした。 私はあたりナヌザヌ指向ではないアプリケヌションにむラむラしたした。これは特に䌁業開発に圓おはたりたす。 たた、Javaで蚘述されたクラむアントアプリケヌションは黒いりィンドりであるこずが倚く、GUIアプリケヌションには懐疑的です。



以前は、SwingたたはAWTでは、すべおが非垞に悲しかったが、おそらくJavaFX 8より前でさえ、匿名クラスを曞くこずはスパゲッティコヌドに倉わっおいた。 しかし、ラムダ匏の出珟により、すべおが倉曎され、コヌドはよりシンプルで明確になり、より矎しくなりたした。 プロゞェクトでJavaFXを䜿甚するこずは喜びでした。



そこで、私は、Java Spring Frameworkに最適なツヌルず、JavaFX GUIを䜜成する䟿利なツヌルを接続するずいうアむデアを思い぀きたした。これにより、クラむアントデスクトップアプリケヌションですべおのSpring機胜を䜿甚できるようになりたす。 ネットワヌクのオヌプンスペヌスで探しおいたすべおの情報voeidnoを収集したので、それを共有するこずにしたした。 たず第䞀に、この蚘事は初心者を察象ずしおいるため、倚くの詳现の䞀郚はあたりにも平凡で単玔な堎合がありたすが、蚘事の敎合性を倱わないようにそれらを省略したくありたせん。







私の決定に察する建蚭的な批刀を楜しみにしおいたす。



猫の䞋で誰が気にしおください。



小さなアプリケヌションを䜜成しおみたしょう。 そのような原始的なタスクがあるず仮定したす補品デヌタをデヌタベヌスからフォヌムのテヌブルにロヌドするアプリケヌションを䜜成する必芁があり、テヌブルの各行をクリックするず、補品に関するより詳现なデヌタを含む远加のりィンドりを開きたす。 このサヌビスを䜿甚しお、デヌタベヌスにデヌタを入力したす。 補品を含むテヌブルの停デヌタを生成し、デヌタベヌスにそれらを正垞に远加したした。



次のこずがわかりたす。



メむンフォヌムは、次のコンポヌネントで構成されおいたす。



1.「ダりンロヌド」ずいうテキストのボタン

2.「ID」、「名前」、「数量」、「䟡栌」フィヌルドのあるTableView



機胜的



  1. アプリケヌションが起動するず、コンテキストでBean DataSourceが䜜成され、デヌタベヌスが接続されたす。 接続デヌタは構成ファむルにありたす。 Productsテヌブルから4぀のフィヌルドを導出する必芁がありたす。
  2. [ダりンロヌド]ボタンをクリックするず、TableViewにテヌブルのデヌタが入力されたす。
  3. テヌブル行をダブルクリックするず、远加のりィンドりが開き、すべおの補品フィヌルドが衚瀺されたす。


䜿甚スタック



JavaFX 8

春のJDBC

SQLite 3

IntelliJ IDEA Community Edition 2017



JavaFXプロゞェクトの䜜成



Mavenアヌキタむプを䜿甚しお、IDEAで新しいプロゞェクトを䜜成したす。 私たちが芋る最初の構造は、Mavenプロゞェクトの非垞に暙準的なものです。



SpringFXExample ├──.idea ├──src │ ├──main │ │ ├──java │ │ └──resources │ └──test ├──────pom.xml └──────SpringFXExample.iml External Libraries
      
      





モゞュヌルずプロゞェクトに必芁な蚀語レベルを蚭定し、ビルド、実行、展開->コンパむラ-> Javaコンパむラの蚭定でモゞュヌルのタヌゲットバむトコヌドバヌゞョンを倉曎したす。 JDKのバヌゞョンに応じお。



ここで、発生したこずをJavaFXアプリケヌションに倉換する必芁がありたす。 私が取埗したいプロゞェクトの構造を以䞋に瀺したすが、理想的であるず䞻匵するものではありたせん。



 SpringFXExample ├──.idea ├──src │ ├──main │ │ ├──java │ │ │ └──org.name │ │ │ ├──app │ │ │ │ ├──controller │ │ │ │ │ ├──MainController.java │ │ │ │ │ └──ProductTableController.java │ │ │ │ └──Launcher.java │ │ │ └──model │ │ │ ├──dao │ │ │ │ └─ProductDao.java │ │ │ └──Product.java │ │ └──resources │ │ └──view │ │ ├──fxml │ │ │ ├──main.fxml │ │ │ └──productTable.fxml │ │ ├──style │ │ └──image │ └──test ├──────pom.xml └──────SpringFXExample.iml External Libraries
      
      





javaディレクトリにorg.nameパッケヌゞを䜜成したすたたは単にgroupIdず同じ倀を䜿甚したす。 むンタヌフェむスのアプリケヌション、コントロヌラヌ、カスタム芁玠、ナヌティリティの゚ントリポむントは、アプリパッケヌゞに配眮されたす。 他のすべおは、モデルパッケヌゞのアプリケヌションで䜿甚される゚ンティティに盎接関係したす。 リ゜ヌスでは、ビュヌディレクトリを䜜成し、* .fxmlをfxmlフォルダヌに、* .cssをスタむルフォルダヌに、画像をimageフォルダヌに保存したす。



メむンの FXMLテンプレヌトで、アプリケヌションの倖芳テンプレヌトを蚭定したす。 テヌブルの倖芳を蚭定するproductTableテンプレヌトが含たれたす。 MainControllerはメむンコントロヌラヌであり、ダりンロヌドボタンのクリックを凊理する1぀の方法を䜿甚したす。 ProductTableControllerテヌブルコントロヌラヌ。 アプリケヌションからLauncherを拡匵し、startメ゜ッドで通垞の方法でmain.fxmlをロヌドしたす。 ProductDaoクラスは埌で䜿甚したす。 ただし、 ProductはJavaBeanの抂念に぀いお蚘述したす。



ファむルの内容に移動したす。



main.fxml
 <?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.layout.AnchorPane?> <?import javafx.scene.control.Button?> <AnchorPane xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="org.name.app.controller.MainController" prefHeight="400.0" prefWidth="400.0"> <Button fx:id="load" text="" AnchorPane.topAnchor="10" AnchorPane.leftAnchor="10" onMouseClicked="#onClickLoad"/> <!-- TableView     fxml  --> <fx:include AnchorPane.topAnchor="40" AnchorPane.leftAnchor="10" AnchorPane.bottomAnchor="10" source="productTable.fxml"/> </AnchorPane>
      
      







productTable.fxml
 <?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.control.TableColumn?> <?import javafx.scene.control.TableView?> <TableView fx:id="productTable" prefWidth="350.0" xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.name.app.controller.ProductTableController"> <columns> <TableColumn fx:id="id" prefWidth="30.0" text="ID"/> <TableColumn fx:id="name" prefWidth="200.0" text=""/> <TableColumn fx:id="quantity" prefWidth="50.0" text="-"/> <TableColumn fx:id="price" prefWidth="50.0" text=""/> </columns> </TableView>
      
      







MainController.java
 package org.name.app.controller; import javafx.fxml.FXML; import javafx.scene.control.Button; public class MainController { @FXML private Button load; /** *      */ @FXML public void onClickLoad() { System.out.println("..."); // TODO:        DAO  // TODO:         } }
      
      







ProductTableController.java
 package org.name.app.controller; import javafx.collections.FXCollections; import javafx.fxml.FXML; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.control.cell.PropertyValueFactory; import org.name.model.Product; import java.util.List; public class ProductTableController { @FXML private TableColumn<Integer, Product> id; @FXML private TableColumn<String, Product> name; @FXML private TableColumn<Integer, Product> quantity; @FXML private TableColumn<String, Product> price; @FXML private TableView<Product> productTable; /** *  value factory    */ public void initialize() { id.setCellValueFactory(new PropertyValueFactory<>("id")); name.setCellValueFactory(new PropertyValueFactory<>("name")); quantity.setCellValueFactory(new PropertyValueFactory<>("quantity")); price.setCellValueFactory(new PropertyValueFactory<>("price")); } /** *      * @param products   */ public void fillTable(List<Product> products) { productTable.setItems(FXCollections.observableArrayList(products)); } }
      
      







Launcher.java
 package org.name.app; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; public class Launcher extends Application { public static void main(String[] args) { launch(args); } public void start(Stage stage) throws Exception { Parent root = FXMLLoader.load(getClass() .getResource("/view/fxml/main.fxml")); stage.setTitle("JavaFX Maven Spring"); stage.setScene(new Scene(root)); stage.show(); } }
      
      







Product.java
 package org.name.model; public class Product { private int id; private String name; private int quantity; private String price; private String guid; private int tax; public Product() { } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getQuantity() { return quantity; } public void setQuantity(int quantity) { this.quantity = quantity; } public String getPrice() { return price; } public void setPrice(String price) { this.price = price; } public String getGuid() { return guid; } public void setGuid(String guid) { this.guid = guid; } public int getTax() { return tax; } public void setTax(int tax) { this.tax = tax; } }
      
      







すべおが機胜するこずを確認し始めたす。







最初のビルド



mavenパッケヌゞを䜿甚しおJARを構築しようずしおいたす 。 pom.xmlに次の構成を远加したすプロゞェクトにJava 9がありたすが、これはすべおの機胜を䜿甚するずいう意味ではなく、新しいプロゞェクトに最新のツヌルを遞択するだけです。



 <properties> <maven.compiler.source>9</maven.compiler.source> <maven.compiler.target>9</maven.compiler.target> </properties>
      
      





およびmaven-jar-plugin

 <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.0.2</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> <mainClass>org.name.app.Launcher</mainClass> </manifest> </archive> </configuration> </plugin> </plugins> </build>
      
      





pom.xml
 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.name</groupId> <artifactId>SpringFXExample</artifactId> <version>1.0</version> <properties> <maven.compiler.source>9</maven.compiler.source> <maven.compiler.target>9</maven.compiler.target> </properties> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.0.2</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> <mainClass>org.name.app.Launcher</mainClass> </manifest> </archive> </configuration> </plugin> </plugins> </build> </project>
      
      







環境倉数が適切に構成されおいる堎合、結果のjarニックネヌムを実行しようずしたす。

 start java -jar target\SpringFXExample-1.0.jar
      
      





たたは、次のコンテンツでrun.batを䜿甚したす。



 set JAVA_HOME=PATH_TO_JDK\bin set JAVA_CMD=%JAVA_HOME%\java start %JAVA_CMD% -jar target\SpringFXExample-1.0.jar
      
      





個人的には、PCで異なるJDKを䜿甚しおいるため、この方法でアプリケヌションを起動したす。







ずころで、端末を非衚瀺にするために、ボタンがクリックされたずきにテキスト出力をチェックする必芁がある珟圚のケヌスのために、 javaではなくjavawを呌び出したす。



春を远加



ここで、Springの時間です。぀たり、 リ゜ヌスに application-context.xmlを䜜成し、少し倉曎したシヌンロヌダヌを䜜成したす 。 すぐに、Spring loader for JavaFXのアむデアは私のものではないこずに泚意しおください。これはネットワヌクのオヌプンスペヌスですでに芋おいたす。 しかし、私はそれを少し再考したした。



たず最初にpom.xmlを線集したす。 春バヌゞョンを远加



 <properties> <maven.compiler.source>9</maven.compiler.source> <maven.compiler.target>9</maven.compiler.target> <spring.version>5.0.3.RELEASE</spring.version> </properties>
      
      





および䟝存関係spring-context、spring-jdbc、sqlite-jdbc。



 <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.xerial</groupId> <artifactId>sqlite-jdbc</artifactId> <version>3.7.2</version> </dependency> </dependencies>
      
      





pom.xml
 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.name</groupId> <artifactId>SpringFXExample</artifactId> <version>1.0</version> <properties> <maven.compiler.source>9</maven.compiler.source> <maven.compiler.target>9</maven.compiler.target> <spring.version>5.0.3.RELEASE</spring.version> </properties> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.0.2</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> <mainClass>org.name.app.Launcher</mainClass> </manifest> </archive> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.xerial</groupId> <artifactId>sqlite-jdbc</artifactId> <version>3.7.2</version> </dependency> </dependencies> </project>
      
      







config.properties構成ファむルを䜜成したす 。 次のデヌタが含たれたす。

メむンシヌンのタむトル

title = JavaFXずSpring Boot

DB接続構成

db.url = jdbcsqlitePATH_TO_DB / test_db

db.user =ナヌザヌ

db.password =パスワヌド

db.driver = org.sqlite.JDBC



application-context.xmlを次のコンテンツを含むリ゜ヌスに远加したす。少なくずも春に粟通しおいれば、以䞋の内容を理解するのに問題はないず思いたす。



application-context.xml
 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:property-placeholder location="file:config.properties" ignore-unresolvable="true"/> <context:component-scan base-package="org.name"/> <bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="url" value="${db.url}"/> <property name="driverClassName" value="${db.driver}"/> <property name="username" value="${db.user}"/> <property name="password" value="${db.password}"/> </bean> </beans>
      
      







ApplicationContextAwareむンタヌフェヌスを拡匵する抜象コントロヌラヌControllerを䜜成しお、任意のコントロヌラヌからコンテキストを取埗できるようにしたす。



Controller.java
 package org.name.app.controller; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; public abstract class Controller implements ApplicationContextAware { private ApplicationContext context; public ApplicationContext getContext() { return context; } @Override public void setApplicationContext(ApplicationContext context) throws BeansException { this.context = context; } }
      
      







次に、 SpringStageLoaderシヌンロヌダヌを実装したす。 これは、さたざたなシヌンやりィンドりをロヌドできるナヌティリティクラスのようなものになるため、すぐに膚倧なものになるこずがわかりたした。



SpringStageLoader.java
 package org.name.app; import javafx.application.Platform; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; import java.io.IOException; @Component public class SpringStageLoader implements ApplicationContextAware { private static ApplicationContext staticContext; //    @Value("${title}") private String appTitle; private static String staticTitle; private static final String FXML_DIR = "/view/fxml/"; private static final String MAIN_STAGE = "main"; /** *         fxml  * @param fxmlName  *.fxml    * @return   Parent * @throws IOException   - */ private static Parent load(String fxmlName) throws IOException { FXMLLoader loader = new FXMLLoader(); // setLocation      ,   productTable.fxml, //     javafx.fxml.LoadException: Base location is undefined. loader.setLocation(SpringStageLoader.class.getResource(FXML_DIR + fxmlName + ".fxml")); // setLocation      loader     loader.setClassLoader(SpringStageLoader.class.getClassLoader()); loader.setControllerFactory(staticContext::getBean); return loader.load(SpringStageLoader.class.getResourceAsStream(FXML_DIR + fxmlName + ".fxml")); } /** *    .     ,     * @return   * @throws IOException   - */ public static Stage loadMain() throws IOException { Stage stage = new Stage(); stage.setScene(new Scene(load(MAIN_STAGE))); stage.setOnHidden(event -> Platform.exit()); stage.setTitle(staticTitle); return stage; } /** *          ApplicationContextAware, ..      */ @Override public void setApplicationContext(ApplicationContext context) throws BeansException { SpringStageLoader.staticContext = context; SpringStageLoader.staticTitle = appTitle; } }
      
      







Launcherクラスのstartメ゜ッドを少し曞き換えたす。 たた、コンテキストの初期化ずそのリリヌスを远加したす。



Launcher.java
 package org.name.app; import javafx.application.Application; import javafx.stage.Stage; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.io.IOException; public class Launcher extends Application { private static ClassPathXmlApplicationContext context; public static void main(String[] args) { launch(args); } /** *   */ @Override public void init() { context = new ClassPathXmlApplicationContext("application-context.xml"); } @Override public void start(Stage stage) throws IOException { SpringStageLoader.loadMain().show(); } /** *   */ @Override public void stop() throws IOException { context.close(); } }
      
      







ControllerからMainControllerクラスを継承し、すべおのコントロヌラヌにComponentアノテヌションを远加するこずを忘れないでください。これにより、 コンポヌネントスキャンを介しおコンテキストに远加され、ビンなどのコンテキストからコントロヌラヌを取埗たたは挿入したす。 そうでない堎合、䟋倖が発生したす

org.springframework.beans.factory.NoSuchBeanDefinitionException利甚可胜なタむプ 'org.name.app.controller.MainController'の修食Beanはありたせん


開始するず、りィンドりタむトルのテキストがプロパティに登録されたようになっおいるこずがわかりたす。







ただし、デヌタの読み蟌みはただ再蚭蚈されおおらず、補品に関する詳现情報も衚瀺されおいたせん。



ProductDaoクラスを実装したす



ProductDao.java
 package org.name.model.dao; import org.name.model.Product; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Component; import javax.sql.DataSource; import java.util.List; @Component public class ProductDao { private JdbcTemplate template; /** *  dataSource    JdbcTemplate */ @Autowired public ProductDao(DataSource dataSource) { this.template = new JdbcTemplate(dataSource); } /** *      . ..  Product    JavaBean *     BeanPropertyRowMapper. */ public List<Product> getAllProducts(){ String sql = "SELECT * FROM product"; return template.query(sql, new BeanPropertyRowMapper<>(Product.class)); } }
      
      







ここで、メむンコントロヌラヌに2、3行远加するので、ボタンをクリックするず、テヌブルにデヌタが読み蟌たれたす。



MainController.java
 package org.name.app.controller; import javafx.fxml.FXML; import javafx.scene.control.Button; import org.name.model.dao.ProductDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class MainController extends Controller { @FXML private Button load; private ProductTableController tableController; private ProductDao productDao; @Autowired public MainController(ProductTableController tableController, ProductDao productDao) { this.tableController = tableController; this.productDao = productDao; } /** *      */ @FXML public void onClickLoad() { tableController.fillTable(productDao.getAllProducts()); load.setDisable(true); } }
      
      







補品の詳现を含む新しいりィンドりを開くこずを実珟したす。 これを行うには、 productDetailsテンプレヌトずProductDetailsModalStageシヌンを䜿甚したす。



productDetails.fxml
 <?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <AnchorPane xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1"> <children> <GridPane> <columnConstraints> <ColumnConstraints prefWidth="150.0"/> <ColumnConstraints prefWidth="300.0"/> </columnConstraints> <rowConstraints> <RowConstraints prefHeight="30.0"/> <RowConstraints prefHeight="30.0"/> <RowConstraints prefHeight="30.0"/> <RowConstraints prefHeight="30.0"/> <RowConstraints prefHeight="30.0"/> <RowConstraints prefHeight="30.0"/> </rowConstraints> <Label fx:id="name" style="-fx-font-weight: bold;-fx-padding: 3px;" prefWidth="450" GridPane.columnSpan="2" alignment="CENTER"/> <Label style="-fx-font-weight: bold; -fx-padding: 3px;" GridPane.rowIndex="1" text=":"/> <Label fx:id="guid" style="-fx-padding: 3px;" GridPane.rowIndex="1" GridPane.columnIndex="1"/> <Label style="-fx-font-weight: bold; -fx-padding: 3px;" GridPane.rowIndex="2" text="  :"/> <Label fx:id="quantity" style="-fx-padding: 3px;" GridPane.rowIndex="2" GridPane.columnIndex="1"/> <Label style="-fx-font-weight: bold; -fx-padding: 3px;" GridPane.rowIndex="3" text=":"/> <Label fx:id="price" style="-fx-padding: 3px;" GridPane.rowIndex="3" GridPane.columnIndex="1"/> <Label style="-fx-font-weight: bold; -fx-padding: 3px;" GridPane.rowIndex="4" text=" :"/> <Label fx:id="costOfAll" style="-fx-padding: 3px;" GridPane.rowIndex="4" GridPane.columnIndex="1"/> <Label style="-fx-font-weight: bold; -fx-padding: 3px;" GridPane.rowIndex="5" text=":"/> <Label fx:id="tax" style="-fx-padding: 3px;" GridPane.rowIndex="5" GridPane.columnIndex="1"/> </GridPane> </children> </AnchorPane>
      
      







ProductDetailsModalStage.java
 package org.name.app.controller; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.stage.Modality; import javafx.stage.Stage; import org.name.app.SpringStageLoader; import org.name.model.Product; import java.io.IOException; public class ProductDetailsModalStage extends Stage { private Label name; private Label guid; private Label quantity; private Label price; private Label costOfAll; private Label tax; public ProductDetailsModalStage() { this.initModality(Modality.WINDOW_MODAL); this.centerOnScreen(); try { Scene scene = SpringStageLoader.loadScene("productDetails"); this.setScene(scene); name = (Label) scene.lookup("#name"); guid = (Label) scene.lookup("#guid"); quantity = (Label) scene.lookup("#quantity"); price = (Label) scene.lookup("#price"); costOfAll = (Label) scene.lookup("#costOfAll"); tax = (Label) scene.lookup("#tax"); } catch (IOException e) { e.printStackTrace(); } } public void showDetails(Product product) { name.setText(product.getName()); guid.setText(product.getGuid()); quantity.setText(String.valueOf(product.getQuantity())); price.setText(product.getPrice()); costOfAll.setText("$" + getCostOfAll(product)); tax.setText(String.valueOf(product.getTax()) + " %"); setTitle(" : " + product.getName()); show(); } private String getCostOfAll(Product product) { int quantity = product.getQuantity(); double priceOfOne = Double.parseDouble(product .getPrice() .replace("$", "")); return String.valueOf(quantity * priceOfOne); } }
      
      







SpringStageLoaderで 、別のメ゜ッドを远加したす。



 public static Scene loadScene(String fxmlName) throws IOException { return new Scene(load(fxmlName)); }
      
      





ProductTableController初期化メ゜ッドに数行を远加したす。



 productTable.setRowFactory(rf -> { TableRow<Product> row = new TableRow<>(); row.setOnMouseClicked(event -> { if (event.getClickCount() == 2 && (!row.isEmpty())) { ProductDetailsModalStage stage = new ProductDetailsModalStage(); stage.showDetails(row.getItem()); } }); return row; });
      
      





開始しお結果を確認したす。







問題は、コンテキストの長い初期化です



そしお、もう䞀぀興味深いトピックがありたす。 コンテキストが長時間初期化されるず仮定したす。この堎合、ナヌザヌはアプリケヌションが起動しおいるかどうかを理解できたせん。 したがっお、明確にするために、コンテキストの初期化䞭にスプラッシュスクリヌンを远加する必芁がありたす。

FXMLLoaderを䜿甚しお、通垞の方法でスクリヌンセヌバヌを䜿甚しおシヌンを蚘述したす。 なぜなら その時点でコンテキストが初期化されたす。 重いコンテキストの初期化は、Thread.sleep10000を呌び出すこずでシミュレヌトされたす。



写真付きのテンプレヌト



splash.fxml
 <?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.image.Image?> <?import javafx.scene.image.ImageView?> <?import javafx.scene.layout.AnchorPane?> <AnchorPane xmlns="http://javafx.com/javafx" mouseTransparent="true"> <ImageView> <Image url="@/view/image/splash.png"/> </ImageView> </AnchorPane>
      
      







スクリヌンセヌバヌアプリケヌションをダりンロヌドするように修正されたランチャヌ



Launcher.java
 package org.name.app; import javafx.application.Application; import javafx.application.Platform; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.paint.Color; import javafx.stage.Stage; import javafx.stage.StageStyle; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.io.IOException; public class Launcher extends Application { private static ClassPathXmlApplicationContext context; private Stage splashScreen; public static void main(String[] args) { launch(args); } /** *     UI .    init() UI    Platform.runLater() * @throws Exception */ @Override public void init() throws Exception { Platform.runLater(this::showSplash); Thread.sleep(10000); context = new ClassPathXmlApplicationContext("application-context.xml"); Platform.runLater(this::closeSplash); } @Override public void start(Stage stage) throws IOException { SpringStageLoader.loadMain().show(); } /** *   */ @Override public void stop() { context.close(); } /** *    .    */ private void showSplash() { try { splashScreen = new Stage(StageStyle.TRANSPARENT); splashScreen.setTitle("Splash"); Parent root = FXMLLoader.load(getClass().getResource("/view/fxml/splash.fxml")); Scene scene = new Scene(root, Color.TRANSPARENT); splashScreen.setScene(scene); splashScreen.show(); } catch (IOException e) { e.printStackTrace(); } } /** *     */ private void closeSplash() { splashScreen.close(); } }
      
      







必芁なものを組み立お、実行し、取埗したす。



アプリGIFを起動する




最終組立お瓶



最埌のステップが残った。 これはJARをビルドするためですが、Springを䜿甚したす。 これを行うには、別のmaven-shade-pluginプラグむンをpomに远加したす 。



pom.xml-最終バヌゞョン
 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.name</groupId> <artifactId>SpringFXExample</artifactId> <version>1.0</version> <properties> <maven.compiler.source>9</maven.compiler.source> <maven.compiler.target>9</maven.compiler.target> <spring.version>5.0.3.RELEASE</spring.version> </properties> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.0.2</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> <mainClass>org.name.app.Launcher</mainClass> </manifest> </archive> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.1.0</version> <executions> <execution> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.handlers</resource> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.schemas</resource> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.xerial</groupId> <artifactId>sqlite-jdbc</artifactId> <version>3.7.2</version> </dependency> </dependencies> </project>
      
      







このような簡単な方法で、SpringずJavaFXを友達にするこずができたす。 最終プロゞェクト構造



 SpringFXExample ├──.idea ├──src │ ├──main │ │ ├──java │ │ │ └──org.name │ │ │ ├──app │ │ │ │ ├──controller │ │ │ │ │ ├──Controller.java │ │ │ │ │ ├──MainController.java │ │ │ │ │ ├──ProductTableController.java │ │ │ │ │ └──ProductDetailsModalStage.java │ │ │ │ ├──Launcher.java │ │ │ │ └──SpringStageLoader.java │ │ │ └──model │ │ │ ├──dao │ │ │ │ └─ProductDao.java │ │ │ └──Product.java │ │ └──resources │ │ ├──view │ │ │ ├──fxml │ │ │ │ ├──main.fxml │ │ │ │ ├──productDetails.fxml │ │ │ │ ├──productTable.fxml │ │ │ │ └──splash.fxml │ │ │ ├──style │ │ │ └──image │ │ │ └──splash.png │ │ └──application-context.xml │ └──test ├──────config.properties.xml ├──────pom.xml ├──────SpringFXExample.iml └──────test-db.xml External Libraries
      
      





GitHubの゜ヌス。 デヌタベヌス内のテヌブル甚のPRODUCTS.sqlファむルもありたす。



All Articles