标签: JavaFX

  • 创建一个基于SpringBoot2.1.x的JavaFX程序

    1.创建SpringBoot项目

    到 https://start.spring.io/ 创建一个SpringBoot2.1.x项目,解压后使用MyEclipse2015导入为maven项目~

    2.引入JavaFX

    对SpringBoot入口程序Application进行改造,继承javafx的application类,并引入接口CommandLineRunner, Consumer<Stage>,接着加入如下代码(高亮部分):

    package com.dgzq;
    
    import java.util.function.Consumer;
    
    import javafx.application.Application;
    import javafx.application.Platform;
    import javafx.scene.Scene;
    import javafx.scene.control.Tab;
    import javafx.scene.control.TabPane;
    import javafx.scene.control.TabPane.TabClosingPolicy;
    import javafx.stage.Stage;
    
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class DgzqApplication extends Application implements CommandLineRunner, Consumer<Stage>{
    
    	public static void main(String[] args) {
    		SpringApplication.run(DgzqApplication.class, args);
    	}
    	
    	@Override
    	public void run(String... args) throws Exception {
    		
    		Platform.runLater(new Runnable() {
    		    @Override
    		    public void run() {
    		    	
    		    	Stage stage = new Stage();
            		
    		    	try {
    					start(stage);
    				} catch (Exception e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
            		
    		    }
    		});
    		
    	}
    
    	@Override
    	public void start(Stage primaryStage) throws Exception {
    		accept(primaryStage);
    	}
    
    	@Override
    	public void accept(Stage stage) {
    		
    		TabPane tabPane = new TabPane();	//增加标签面板
    		tabPane.setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE);
    		
    		Scene scene = new Scene(tabPane, 900, 690);
    		stage.setScene(scene);
    		stage.setTitle("测试界面");
    		
    		Tab tab1 = new Tab("标签页1");
    		Tab tab2 = new Tab("标签页2");
    		tabPane.getTabs().addAll(tab1,tab2);
    		tabPane.getSelectionModel().select(tab1);	//设置默认选中
    		
    		stage.show();
    	}
    
    }
    

    然后启动,出现如下界面则为成功:

    ac571e727fe9d73b3500c54a3e2117c

     

    3.增加预加载页面

    在pom.xml加入如下依赖:

    		<!-- SpringBoot2.x与JavaFX的集成 -->
    		<!-- https://mvnrepository.com/artifact/de.roskenet/springboot-javafx-support -->
    		<dependency>
    		    <groupId>de.roskenet</groupId>
    		    <artifactId>springboot-javafx-support</artifactId>
    		    <version>2.1.6</version>
    		</dependency>

     

    新增一个启动入口文件如MainApplication.java用于展示欢迎界面,代码如下:

    package com.dgzq;
    
    import java.io.File;
    
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    import de.felixroske.jfxsupport.AbstractJavaFxApplicationSupport;
    import de.felixroske.jfxsupport.SplashScreen;
    import javafx.scene.Scene;
    import javafx.scene.control.Alert;
    import javafx.stage.Stage;
    import javafx.stage.StageStyle;
    import javafx.scene.paint.Color;
    
    @SpringBootApplication
    public class MainApplication extends AbstractJavaFxApplicationSupport {
    	
    	public static SplashScreen splashScreen;
    	public static Stage splashStage;
    	public static Scene splashScene;
    	
        public static void main(String[] args) {
        	
        	//启动(若需要以fxml形式展示主界面,则第二个传参可以为"MainStageView.class"之类的)
        	launch(MainApplication.class, null, args);
            
        }
    
        @Override
        public void start(Stage stage) throws Exception {
    
        	MainApplication.splashScreen = new SplashScreen();
        	MainApplication.splashStage = new Stage(StageStyle.TRANSPARENT);
        	MainApplication.splashScene = new Scene(splashScreen.getParent(), Color.TRANSPARENT);
        	MainApplication.splashStage.setScene(splashScene);
        	MainApplication.splashStage.initStyle(StageStyle.TRANSPARENT);
        	MainApplication.splashStage.show();
    
        }
        
    }

    在预加载完成后还要再正式界面中隐藏掉本界面,因此要在原来的application类的stage.show()前面加入如下代码:

    MainApplication.splashStage.hide();
    MainApplication.splashStage.setScene(null);

    然后注释掉原来的application启动类中的main方法:

    /*public static void main(String[] args) {
    	SpringApplication.run(DgzqApplication.class, args);
    }*/

    最后启动刚刚新建的MainApplication.java,便会出现中间界面:

    d294a0cca4b571832aaa7b9c70f8363

    好了,大功告成。如果还需要引入sqlite数据库,则可以继续往下操作。

    4.引入hibernate并使用sqlite数据库

    在MainApplication中的 下方加入如下代码,以提示sqlite是否存在:

        	File databaseFile = new File("sqlite3.db");
        	if(!databaseFile.exists()){
    	    	Alert alert = new Alert(Alert.AlertType.INFORMATION);
    			alert.setTitle("错误");
    			alert.setHeaderText(null);
    			alert.setContentText("找不到数据库文件:sqlite3.db(本次运行将自动创建全新的空白数据库)");
    			alert.showAndWait();
        	}

    再pom.xml中加入如下依赖:

    	<!-- sqlite3驱动包 -->
            <!-- https://mvnrepository.com/artifact/org.xerial/sqlite-jdbc -->
    		<dependency>
    		    <groupId>org.xerial</groupId>
    		    <artifactId>sqlite-jdbc</artifactId>
    		    <version>3.28.0</version>
    		</dependency>
    		
    		<!-- SpringBoot与hibernate的集成配置 -->
    		<dependency>
    		    <groupId>org.springframework.boot</groupId>
    		    <artifactId>spring-boot-starter-data-jpa</artifactId>
    		</dependency>
    		<!-- SpringBoot使用Hibernate的SessionFactory -->
    		<dependency>
    		    <groupId>org.hibernate</groupId>
    		    <artifactId>hibernate-core</artifactId>
    		    <version>5.0.12.Final</version>
    		</dependency>
    		<dependency>
    		    <groupId>org.hibernate</groupId>
    		    <artifactId>hibernate-entitymanager</artifactId>
    		    <version>5.0.12.Final</version>
    		</dependency>
    		
    		<!-- SpringBoot2.x与JavaFX的集成 -->
    		<!-- https://mvnrepository.com/artifact/de.roskenet/springboot-javafx-support -->
    		<dependency>
    		    <groupId>de.roskenet</groupId>
    		    <artifactId>springboot-javafx-support</artifactId>
    		    <version>2.1.6</version>
    		</dependency>

     

    对原来的Application进行修改(加入高亮部分):

    package com.dgzq;
    
    import java.util.function.Consumer;
    
    import javafx.application.Application;
    import javafx.application.Platform;
    import javafx.scene.Scene;
    import javafx.scene.control.Tab;
    import javafx.scene.control.TabPane;
    import javafx.scene.control.TabPane.TabClosingPolicy;
    import javafx.stage.Stage;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    import org.springframework.orm.jpa.vendor.HibernateJpaSessionFactoryBean;
    
    @SpringBootApplication
    public class DgzqApplication extends Application implements CommandLineRunner, Consumer<Stage>{
    	
    	public static SessionFactory sessionFactory;
    	@Autowired
    	public void setSessionFactory(SessionFactory sessionFactory) {
    		DgzqApplication.sessionFactory = sessionFactory;
    	}
    	
    	@Bean
        public HibernateJpaSessionFactoryBean sessionFactory() {
            return new HibernateJpaSessionFactoryBean();
        }
    
    	/*public static void main(String[] args) {
    		SpringApplication.run(DgzqApplication.class, args);
    	}*/
    	
    	@Override
    	public void run(String... args) throws Exception {
    		
    		Platform.runLater(new Runnable() {
    		    @Override
    		    public void run() {
    		    	
    		    	Stage stage = new Stage();
            		
    		    	try {
    					start(stage);
    				} catch (Exception e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
            		
    		    }
    		});
    		
    	}
    
    	@Override
    	public void start(Stage primaryStage) throws Exception {
    		accept(primaryStage);
    	}
    
    	@Override
    	public void accept(Stage stage) {
    		
    		System.out.println("MainJavaFxApplication被实例化了");
    		System.out.println("MainJavaFxApplication.sessionFactory = "+sessionFactory);
    		
    		TabPane tabPane = new TabPane();	//增加标签面板
    		tabPane.setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE);
    		
    		Scene scene = new Scene(tabPane, 900, 690);
    		stage.setScene(scene);
    		stage.setTitle("测试界面");
    		
    		Tab tab1 = new Tab("标签页1");
    		Tab tab2 = new Tab("标签页2");
    		tabPane.getTabs().addAll(tab1,tab2);
    		tabPane.getSelectionModel().select(tab1);	//设置默认选中
    		
    		MainApplication.splashStage.hide();
    		MainApplication.splashStage.setScene(null);
    		
    		stage.show();
    	}
    
    }
    

    增加sqlite的方言类SQLiteDialect.java:

    package com.fenji;
    
    import java.sql.Types;
    
    import org.hibernate.dialect.Dialect;
    import org.hibernate.dialect.function.StandardSQLFunction;
    import org.hibernate.dialect.function.SQLFunctionTemplate;
    import org.hibernate.dialect.function.VarArgsSQLFunction;
    import org.hibernate.type.StandardBasicTypes;
    
    public class SQLiteDialect extends Dialect {
        public SQLiteDialect() {
            super();
            registerColumnType(Types.BIT, "integer");
            registerColumnType(Types.TINYINT, "tinyint");
            registerColumnType(Types.SMALLINT, "smallint");
            registerColumnType(Types.INTEGER, "integer");
            registerColumnType(Types.BIGINT, "bigint");
            registerColumnType(Types.FLOAT, "float");
            registerColumnType(Types.REAL, "real");
            registerColumnType(Types.DOUBLE, "double");
            registerColumnType(Types.NUMERIC, "numeric");
            registerColumnType(Types.DECIMAL, "decimal");
            registerColumnType(Types.CHAR, "char");
            registerColumnType(Types.VARCHAR, "varchar");
            registerColumnType(Types.LONGVARCHAR, "longvarchar");
            registerColumnType(Types.DATE, "date");
            registerColumnType(Types.TIME, "time");
            registerColumnType(Types.TIMESTAMP, "timestamp");
            registerColumnType(Types.BINARY, "blob");
            registerColumnType(Types.VARBINARY, "blob");
            registerColumnType(Types.LONGVARBINARY, "blob");
            // registerColumnType(Types.NULL, "null");
            registerColumnType(Types.BLOB, "blob");
            registerColumnType(Types.CLOB, "clob");
            registerColumnType(Types.BOOLEAN, "integer");
    
            registerFunction("concat", new VarArgsSQLFunction(StandardBasicTypes.STRING, "", "||", ""));
            registerFunction("mod", new SQLFunctionTemplate(StandardBasicTypes.INTEGER, "?1 % ?2"));
            registerFunction("substr", new StandardSQLFunction("substr", StandardBasicTypes.STRING));
            registerFunction("substring", new StandardSQLFunction("substr", StandardBasicTypes.STRING));
        }
    
        public boolean supportsIdentityColumns() {
            return true;
        }
    
        public boolean hasDataTypeInIdentityColumn() {
            return false;
        }
    
        public String getIdentityColumnString() {
            return "integer";
        }
    
        public String getIdentitySelectString() {
            return "select last_insert_rowid()";
        }
    
        public boolean supportsLimit() {
            return true;
        }
    
        public String getLimitString(String query, boolean hasOffset) {
            return new StringBuffer(query.length() + 20).append(query).append(hasOffset ? " limit ? offset ?" : " limit ?")
                    .toString();
        }
    
        public boolean supportsTemporaryTables() {
            return true;
        }
    
        public String getCreateTemporaryTableString() {
            return "create temporary table if not exists";
        }
    
        public boolean dropTemporaryTableAfterUse() {
            return false;
        }
    
        public boolean supportsCurrentTimestampSelection() {
            return true;
        }
    
        public boolean isCurrentTimestampSelectStringCallable() {
            return false;
        }
    
        public String getCurrentTimestampSelectString() {
            return "select current_timestamp";
        }
    
        public boolean supportsUnionAll() {
            return true;
        }
    
        public boolean hasAlterTable() {
            return false;
        }
    
        public boolean dropConstraints() {
            return false;
        }
    
        public String getAddColumnString() {
            return "add column";
        }
    
        public String getForUpdateString() {
            return "";
        }
    
        public boolean supportsOuterJoinForUpdate() {
            return false;
        }
    
        public String getDropForeignKeyString() {
            throw new UnsupportedOperationException("No drop foreign key syntax supported by SQLiteDialect");
        }
    
        public String getAddForeignKeyConstraintString(String constraintName, String[] foreignKey, String referencedTable,
                String[] primaryKey, boolean referencesPrimaryKey) {
            throw new UnsupportedOperationException("No add foreign key syntax supported by SQLiteDialect");
        }
    
        public String getAddPrimaryKeyConstraintString(String constraintName) {
            throw new UnsupportedOperationException("No add primary key syntax supported by SQLiteDialect");
        }
    
        public boolean supportsIfExistsBeforeTableName() {
            return true;
        }
    
        public boolean supportsCascadeDelete() {
            return false;
        }
    
        @Override
        public boolean bindLimitParametersInReverseOrder() {
            return true;
        }
    }

    增加配置文件application.properties用于配置数据库(注意高亮行,要指向刚刚创建的方言类SQLiteDialect.java):

    spring.datasource.driver-class-name=org.sqlite.JDBC
    spring.datasource.url=jdbc:sqlite:sqlite3.db
    
    # Specify the DBMS
    #spring.jpa.database=SQLite
    # Show or not log for each sql query
    spring.jpa.show-sql=true
    # Hibernate ddl auto (create, create-drop, update)
    spring.jpa.hibernate.ddl-auto=update
    # Naming strategy
    spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy
    # stripped before adding them to the entity manager
    #spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
    spring.jpa.properties.hibernate.dialect=com.dgzq.SQLiteDialect
    # table column upcase problem
    spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
    spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
    # auto inject sessionFactory bean
    spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext

    好了,运行MainApplication看看效果:

    639fccfb32a10d16ee5a29089e0094f

    如图所示,输入sessionFactory不为空,则注入成功,后面大家自由发挥吧!

    5.补充:记得指定maven打包时的启动入口

    在pom.xml中加入如下高亮代码

    	<build>
    		<plugins>
    			<plugin>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-maven-plugin</artifactId>
    				<configuration>
    					<mainClass>com.dgzq.MainApplication</mainClass>
    				</configuration>
    			</plugin>
    		</plugins>
    	</build>

    大功告成!