java的ui库分为三代,第一代是awt,第二代是swing,第三代就是javafx了,互相之间是替代关系。桌面开发现在一般用swing和javafx,今天用javafx开发一个简单的日历查询应用。

最终效果如下:

Java扩展桌面 java桌面工具_javafx


git地址:JavaFX日历实现


javafx开发

javafx开发界面开发有两种方式:
1.通过Java代码来编写。
所有的界面和逻辑都通过Java代码来实现,写的东西比较多。

2.通过JavaFX Scene Builder + Java代码来编写实现。
JavaFX Scene Builder是一种可视化设计工具,它允许通过拖放快速创建应用程序界面。 并且代码创建为XML格式的文件。通过JavaFX Scene Builder拖拽来开发界面,Java来实现逻辑比较简单快速。

下面的实例是通过JavaFX Scene Builder + Java实现的。


下载JavaFX Scene Builder

官网下载:JavaFX Scene Builder官网


创建项目

idea新建项目选择Java Fx。

(注意:尽量使用jdk8及8以上,jdk8以下是没有自带javafx的,需要自己引入jar包,自行百度)

Java扩展桌面 java桌面工具_Java扩展桌面_02


建完后的结构如下,Main程序的入口,sample.fxml用于JavaFX Scene Builder拖拽生成界面,Controller用于绑定界面和和处理监听事件:

Java扩展桌面 java桌面工具_awt_03

选择sample.fxml右键open in sceneBuilder,然后选择

Java扩展桌面 java桌面工具_javafx_04


然后选择安装好的JavaFX Scene Builder

Java扩展桌面 java桌面工具_awt_05

界面设计

从左上角选择相应的组件到中间进行布局,如图我选择了7个组件,左边是选择的所有组件信息。在中间选择任意一个组件右边都有组件的具体设置,比如长度、宽度、输入框默认提示,组件的名称等。

Java扩展桌面 java桌面工具_Java扩展桌面_06


设置组件的名称,后面Java里会用到:

Java扩展桌面 java桌面工具_swing_07


保存后sample.fxml内容变成如下:

要手动加上 fx:cnotallow="sample.Controller"将sample.fxml文件和Controller文件关联绑定,这样下面写Java代码才能使用fxml里的东西。

<?xml version="1.0" encoding="UTF-8"?>

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

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="399.0" prefWidth="627.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
   <children>
      <Button fx:id="id_1" layoutX="103.0" layoutY="120.0" mnemonicParsing="false" onAction="#buttonAction1" prefHeight="30.0" prefWidth="119.0" text="获取日历" textFill="#3a6f2e" />
      <TextField fx:id="text_1" layoutX="102.0" layoutY="61.0" promptText="请输入年份,如:2021" />
      <TextField fx:id="text_2" layoutX="380.0" layoutY="61.0" promptText="请输入月份,如:2" />
      <Text layoutX="48.0" layoutY="82.0" strokeType="OUTSIDE" strokeWidth="0.0" text=" 年:" wrappingWidth="35.0" />
      <Text layoutX="332.0" layoutY="82.0" strokeType="OUTSIDE" strokeWidth="0.0" text=" 月:" wrappingWidth="35.0" />
      <TextArea fx:id="text_3" layoutX="167.0" layoutY="197.0" prefHeight="146.0" prefWidth="274.0" />
   </children>
</AnchorPane>

代码:

Controller:

package sample;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import java.net.URL;
import java.util.ResourceBundle;

public class Controller implements Initializable {
    @FXML
    private Button id_1;
    @FXML
    private TextField text_1;//从fxml获取组件text_1,用于读取年
    @FXML
    private TextField text_2;//从fxml获取组件text_2,用于读取月
    @FXML
    private TextArea text_3;//从fxml获取组件text_3,用于输出

    @Override
    public void initialize(URL location, ResourceBundle resources)
    {}

    //点击按钮时触发的事件
    public void buttonAction1(ActionEvent actionEvent)
    {
        String year = text_1.getText();//获取文本框输入的内容
        String month = text_2.getText();//获取文本框输入的内容
        String result=Service.calculationDate(year,month);
        text_3.setText(result);
    }
}

service:

package sample;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;

public class Service {
    public static String calculationDate(String y, String m) {
        char[] yearChar = y.toCharArray();
        char[] monthChar = m.toCharArray();
        if(null==y||y.length()==0||null==m||m.length()==0){
            return "年份或月份不能输入为空。";
        }

        for (int i = 0; i < yearChar.length; i++) {
            boolean isOrNo = Character.isDigit(yearChar[i]);
            if (yearChar[0] == '0' || !isOrNo) {
                return "年份输入错误,请输入正确的年份。";
            }
        }

        for (int i = 0; i < monthChar.length; i++) {
            boolean isOrNo = Character.isDigit(monthChar[i]);
            if (yearChar[0] == '0' || !isOrNo) {
                return "月份输入错误,请输入正确的月份。";
            }
        }

        int year = Integer.parseInt(y);
        int month = Integer.parseInt(m);

        if (year < 1900||(year==1900&&month==1)) {
            return "年份需要大于等于1900。当年份是1900时,月份需要大于1。";
        }

        if (month > 12) {
            return "月份输入错误,请输入正确的月份。";
        }

        LocalDate endDate = LocalDate.of(year, month, 1);//设置输入的日期
        LocalDate startDate = LocalDate.of(1900, 1, 1);
        long sumDay = startDate.until(endDate, ChronoUnit.DAYS);//总相差的天数:3657
        /*以上代码计算1900年1月1号到输入的年月的总天数,如输入2018和8,则计算1900.1.1-2018.7.31的天数*/

        long xingQi = (sumDay + 1) % 7; //xingQi用来计算输入的月份1号星期几
        long everydayXingQi = sumDay + 1;
        int monthDay = endDate.lengthOfMonth();//用来接收输入的月份有几天

        String result = "日\t一\t二\t三\t四\t五\t六\n";
        for (int i = 0; i < xingQi; i++) {    //输出每月1号前的空格
            result += "\t";
        }
        for (int i = 1; i <= monthDay; i++) {  //输出每个月的天数和控制换行
            if (everydayXingQi % 7 == 6) {
                result += i + "\n";
            } else {
                result += i + "\t";
            }
            everydayXingQi++;
        }
        return result;
    }
}

Main:

package sample;

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

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        //引用sample.fxml页面布局
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        //设置窗口名称
        primaryStage.setTitle("日历");
        //设置窗口大小
        primaryStage.setScene(new Scene(root, 627, 399));
        //固定窗口大小使其无法最大化
        primaryStage.setResizable(false);
        //设置窗口的图标.
        primaryStage.getIcons().add(new Image("/sample/image/rili.jpg"));
        primaryStage.show();
    }

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

启动项目就ok了。


打成jar包:

Java扩展桌面 java桌面工具_swing_08

Java扩展桌面 java桌面工具_javafx_09

当然你也可以把写好的程序打成jar包或exe程序,打包如下:

Java扩展桌面 java桌面工具_awt_10


Java扩展桌面 java桌面工具_javafx_11


Java扩展桌面 java桌面工具_javafx_12


javaFxText下会生成一个exe文件

Java扩展桌面 java桌面工具_Java扩展桌面_13


文件夹中打开后,双击就可以运行了

Java扩展桌面 java桌面工具_awt_14


Java扩展桌面 java桌面工具_javafx_15


但是这个exe文件太难找了,一找找半天,本来想着创建个快捷方式,但是快捷方式只支持绝对路径,没办法,我们可以回到上层目录新建个txt文件输入:

start JavaFxTest\JavaFxTest.exe
exit

start 后面跟自己的文件夹名和exe名。
保存文件后把后缀改为bat

以后双击就能用了。

Java扩展桌面 java桌面工具_awt_16


关于其他打包方式目前还没试,比如先打成jar包,再通过其他工具打成exe文件。
参考:将java打包成exe——在没有jdk或jre的机器上运行Java项目java工具(一):在没有jdk环境的电脑上运行java项目,制作exe文件


如果你对 javaFX 感兴趣,你可以看下我 gitgub上使用 javaFX 开发的一个应用: XTool

Java扩展桌面 java桌面工具_swing_17