JavaFX入门和使用实践

JavaFX入门和使用实践

一、前言

  • 操作系统:Windows 10 专业版
  • JDK 版本:1.8
  • 开发工具:IntelliJ IDEA 2020.2.2

JavaFX:https://www.oracle.com/cn/java/technologies/javase/javafx-overview.html

OpenJFX:https://openjfx.io/

JavaFX中文资料:http://www.javafxchina.net/blog/docs/tutorial3/

JavaFX Scene Builder Archive:https://www.oracle.com/java/technologies/javafxscenebuilder-1x-archive-downloads.html

POI 操作:https://blog.csdn.net/u011424614/article/details/104370924

创建 JavaFX 项目:https://blog.csdn.net/u011424614/article/details/112383294

二、正文

场景说明: 读取并显示 txt 文件的内容,最后打包项目为 exe 程序

1.创建项目

1)创建项目

  • 使用 IntelliJ IDEA 开发工具创建 JavaFX 项目,并添加 maven 构建工具的支持;这步可以参考之前的文章

创建项目:https://blog.csdn.net/u011424614/article/details/112383294

2)移动 fxml 文件

  • sample.fxml 移动到 resources 文件夹中,修改 Main.java 的 fxml 文件引用路径
package com.sample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("/sample.fxml"));
        primaryStage.setTitle("TXT读取工具 V1.0");
        primaryStage.setScene(new Scene(root, 580, 400));
        primaryStage.setResizable(false); // 禁止缩放窗口
        primaryStage.show();
    }


    public static void main(String[] args) {
        launch(args);
    }
}

2.界面布局

  • 打开 sample.fxml ,点击编辑区域左下角的 Scene Builder 选项卡

在这里插入图片描述

如果出现提示:Failed to open the file in the Scene Builder.

解决方法查看当前文章的 三、其它 - 1.Scene Builder kit使用

  • 左侧选择控件,拖拽到显示区域;先选择容器 Pane,然后选择其它控件

在这里插入图片描述

  • 控件:Label、TextField(属性:Editable 去勾)、Button、TextArea(属性:Editable 去勾)
<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.sample.Controller">
   <children>
      <Label layoutX="231.0" layoutY="14.0" text="TXT读取工具">
         <font>
            <Font size="24.0" />
         </font>
      </Label>
      <Label layoutX="37.0" layoutY="77.0" text="请选择文件" />
      <TextField fx:id="tfShowPath" editable="false" layoutX="118.0" layoutY="72.0" prefHeight="30.0" prefWidth="335.0" />
      <Button fx:id="btnOpenFile" layoutX="462.0" layoutY="72.0" mnemonicParsing="false" text="打开文件..." />
      <TextArea fx:id="taShowText" editable="false" layoutX="37.0" layoutY="119.0" prefHeight="258.0" prefWidth="517.0" />
   </children>
</Pane>

3.业务处理

1)绑定控件

  • sample.fxml 文件的 Pane 容器指定 Controller.java

  • sample.fxml 文件的控件设置ID fx:id="controlsId"

  • Controller.java 实现 Initializable

  • Controller.java 定义与 fxml 中 id 名称相同的属性,并添加注解 @FXML

2)选择文件

3)读取并显示

  • 注意: 代码中控件的引用是 javafx.scene.control ;而不是 java.awt
  • 添加日志依赖:
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.30</version>
</dependency>
  • 新增 logback 配置文件:resource / logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
	<!--定义日志文件的存储地址 -->
	<property name="LOG_HOME" value="../logs" />

	<!--<property name="COLOR_PATTERN" value="%black(%contextName-) %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta( %replace(%caller{1}){'\t|Caller.{1}0|\r\n', ''})- %gray(%msg%xEx%n)" />-->
	<!-- 控制台输出 -->
	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
		<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
			<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n</pattern>
		</encoder>
	</appender>

	<!-- 按照每天生成日志文件 -->
	<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
		<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
			<!--日志文件输出的文件名 -->
			<FileNamePattern>${LOG_HOME}/jeecgboot-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
			<!--日志文件保留天数 -->
			<MaxHistory>30</MaxHistory>
			<maxFileSize>20MB</maxFileSize>
		</rollingPolicy>
		<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
			<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n</pattern>
		</encoder>
	</appender>

	<!-- 生成 error html格式日志开始 -->
	<appender name="HTML" class="ch.qos.logback.core.FileAppender">
		<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
			<!--设置日志级别,过滤掉info日志,只输入error日志-->
			<level>ERROR</level>
		</filter>
		<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
			<layout class="ch.qos.logback.classic.html.HTMLLayout">
				<pattern>%p%d%msg%M%F{32}%L</pattern>
			</layout>
		</encoder>
		<file>${LOG_HOME}/error-log.html</file>
	</appender>
	<!-- 生成 error html格式日志结束 -->

	<!-- 每天生成一个html格式的日志开始 -->
	<appender name="FILE_HTML" class="ch.qos.logback.core.rolling.RollingFileAppender">
		<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
			<!--日志文件输出的文件名 -->
			<FileNamePattern>${LOG_HOME}/jeecgboot-%d{yyyy-MM-dd}.%i.html</FileNamePattern>
			<!--日志文件保留天数 -->
			<MaxHistory>30</MaxHistory>
			<MaxFileSize>10MB</MaxFileSize>
		</rollingPolicy>
		<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
			<layout class="ch.qos.logback.classic.html.HTMLLayout">
				<pattern>%p%d%msg%M%F{32}%L</pattern>
			</layout>
		</encoder>
	</appender>
	<!-- 每天生成一个html格式的日志结束 -->

	<!-- 日志输出级别 -->
	<root level="INFO">
		<appender-ref ref="STDOUT" />
		<appender-ref ref="FILE" />
		<appender-ref ref="HTML" />
		<appender-ref ref="FILE_HTML" />
	</root>

</configuration>
  • Controller.java 代码
package com.sample;

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.stage.FileChooser;
import javafx.stage.Window;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.URL;
import java.util.ResourceBundle;

public class Controller implements Initializable {
    @FXML
    private TextField tfShowPath; // 显示文件路径
    @FXML
    private Button btnOpenFile; // 打开文件按钮
    @FXML
    private TextArea taShowText; // 显示内容
    // 日志
    private Logger logger = LoggerFactory.getLogger(this.getClass());


    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // 打开文件按钮-事件绑定
        handleBtnOpenFile(location, resources);
    }

    /**
     * 打开文件按钮-事件绑定
     * @param location
     * @param resources
     * */
    private void handleBtnOpenFile(URL location, ResourceBundle resources) {
        // 按钮绑定事件
        btnOpenFile.setOnAction(e -> {
            // 文件选择控件
            FileChooser fileChooser = new FileChooser();
            // 过滤文件格式
            /*FileChooser.ExtensionFilter xlsFileChooser
                    = new FileChooser.ExtensionFilter("Excel files (*.xls)","*.xls");
            FileChooser.ExtensionFilter xlsxFileChooser
                    = new FileChooser.ExtensionFilter("Excel files (*.xlsx)","*.xlsx");*/
            FileChooser.ExtensionFilter txtFileChooser
                    = new FileChooser.ExtensionFilter("TXT files (*.txt)","*.txt");
            fileChooser.getExtensionFilters().addAll(txtFileChooser);
            // 打开选择窗口
            Window window = ((Node)e.getSource()).getScene().getWindow();
            File chooseFile = fileChooser.showOpenDialog(window);
            if(chooseFile != null){
                // System.out.println(chooseFile.getAbsolutePath());
                // 设置路径到显示控件
                tfShowPath.setText(chooseFile.getAbsolutePath());
                // 读取数据
                String result = readFile(chooseFile.getAbsolutePath());
                // 显示内容
                taShowText.setText(result);
            }
        });
    }

    /**
     * 根据文件路径,读取内容
     * @param filepath 文件路径
     * */
    public String readFile(String filepath){
        File file = null;
        FileInputStream fileInputStream = null;
        InputStreamReader inputStreamReader = null;
        BufferedReader bufferedReader = null;
        try {
            file = new File(filepath);
            if(file.isFile() && file.exists()){
                // 读取内容
                fileInputStream = new FileInputStream(file);
                inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");
                bufferedReader = new BufferedReader(inputStreamReader);
                StringBuffer stringBuffer = new StringBuffer();
                String lineText = "";
                while ((lineText = bufferedReader.readLine()) != null){
                    stringBuffer.append(lineText).append("\n");
                }
                logger.info(stringBuffer.toString());
                return stringBuffer.toString();
            }else {
                String msg = "文件路径无效.";
                logger.info(msg);
                return msg;
            }
        } catch (IOException e) {
            // e.printStackTrace();
            String msg = "读取数据错误:"+e.getMessage();
            logger.error(msg);
            return msg;
        }
    }

}

4.打包项目

  • 工具栏 File - Project Structure... - Artifacts 选项卡 - + 加号 - JavaFx Application - From module '项目名称'

在这里插入图片描述

  • 选择需要打包的 maven 依赖包 :Output Layout 选项卡 - Available Elements 窗口 - 项目名称右击 - Put into Output Root

在这里插入图片描述

  • Java Fx 选项卡 配置项目信息
    1. Application class : 必填,用于打包后,作为启动入口)
    2. Native bundle : 选择 all ;表示 jar 和 exe 都打包,默认只打包 jar 包

在这里插入图片描述

  • Apply 应用设置
  • 工具栏 Build - Build Artifacts...

在这里插入图片描述

  • 打包后目录:项目根目录 out 文件夹,jar 包(需要 jre 环境)和 exe 都可以双击打开

三、其它

1.Scene Builder Kit使用

说明: 这里有 两种方法 ,请自行选择

方法一: 使用 idea 的 Scene Builder Kit

1) 根据 Idea 提示,获取 scenebuilderkit-11.0.5.jar 的下载路径,使用科学上网的方式,下载 jar 包

提示提取的路径:https://cache-redirector.jetbrains.com/jetbrains.bintray.com/intellij-third-party-dependencies/org/jetbrains/intellij/deps/scenebuilderkit/11.0.5/scenebuilderkit-11.0.5.jar

2) 将下载的 scenebuilderkit-11.0.5.jar 拷贝到 idea 安装目录的 lib 文件夹下

3) 打开 fxml 文件,编辑窗口左下角,切换到 Scene Builder 选项卡,点击 Download JavaFx ,等待其它 jar 包下载完成

在这里插入图片描述

方法二: 使用 Oracle 官网的 Scene Builder Kit

1)下载并安装

官网下载:https://www.oracle.com/java/technologies/javafxscenebuilder-1x-archive-downloads.html

在这里插入图片描述

  • 下载并安装 javafx_scenebuilder-2_0-windows.msi

2)IDEA 配置

  • 工具栏 File - Settings...

    (1)Plugins 菜单:查询 JavaFX ;确保以安装和启用

    (2) Languages & Frameworks 菜单:点击 JavaFX ,选择 SBK exe 文件

在这里插入图片描述

3)使用

  • fxml 文件右击 - Open In SceneBuilder

在这里插入图片描述

2.ChoiceBox控件

  • 选择触发事件
cbSelectId.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                // System.out.println(newValue+" newValue="+cbLngLatField.getItems().get(newValue.intValue()));
                cbLngLatFieldIndex = newValue.intValue();
            }
        });
  • 设置默认值(需要先设置数据项,才能设置数据项中的值)
cbSelectId.getItems().removeAll(cbSelectId.getItems()); // 先清空之前的数据项
cbSelectId.getItems().addAll(datas); // 添加到下拉框中
cbSelectId.setValue("abc"); // 默认选中项
  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
JavaFX可以通过使用场景(Scene)对象来实现场景切换。下面是一个简单的示例代码,演示了如何实现场景切换: ```java import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class SceneSwitchingExample extends Application { private Stage primaryStage; @Override public void start(Stage primaryStage) { this.primaryStage = primaryStage; // 创建两个场景 Scene scene1 = createScene("Scene 1", "Switch to Scene 2"); Scene scene2 = createScene("Scene 2", "Switch to Scene 1"); // 初始显示第一个场景 primaryStage.setScene(scene1); primaryStage.setTitle("Scene Switching Example"); primaryStage.show(); // 按钮点击事件,切换到另一个场景 Button button = (Button) scene1.getRoot().lookup("#button"); button.setOnAction(event -> primaryStage.setScene(scene2)); Button backButton = (Button) scene2.getRoot().lookup("#button"); backButton.setOnAction(event -> primaryStage.setScene(scene1)); } // 创建场景的辅助方法 private Scene createScene(String title, String buttonText) { Button button = new Button(buttonText); button.setId("button"); StackPane root = new StackPane(); root.getChildren().add(button); return new Scene(root, 300, 200); } public static void main(String[] args) { launch(args); } } ``` 在上面的示例中,我们创建了两个场景(scene1和scene2),并在每个场景中放置了一个按钮。按钮点击事件触发时,我们使用`setScene()`方法将当前场景切换到另一个场景。 这仅仅是一个简单的示例,你可以根据自己的需求进行场景的设计和切换。希
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

趴着喝可乐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值