众所周知,SpringBoot是一款强大的Javaweb开发程序,这得益于其构造了一个Spring容器,然后通过依赖注入和控制反转,维护起一套Java对象和实例的管理机制,方便开发者去使用。在web应用开发的应用中,Springboot在Java层应用非常广,同样的,也可以利用SpringBoot来编写桌面程序。
标准的JavaFx代码
JavaFx是java中比较新的桌面端应用程序开发框架,一般来说,简单的使用JavaFx编写一个桌面程序的代码如下:
下面是一个实现一个树形结构的javafx程序
package com.demo123567.desktop.auto_tools;
import com.demo123567.desktop.auto_tools.menu.FxUtils;
import com.demo123567.desktop.auto_tools.utils.DatetimeUtil;
import com.demo123567.desktop.auto_tools.utils.Json;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.jcraft.jsch.*;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.TextFieldTreeCell;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import javafx.util.converter.DefaultStringConverter;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.LocalDateTime;
import java.util.*;
public class SftpExample extends Application {
@Override
public void start(Stage primaryStage) {
// 创建根节点
TreeItem<String> rootItem = new TreeItem<>("Root");
// 创建TreeView
TreeView<String> treeView = new TreeView<>(rootItem);
// 创建一个按钮,用于动态添加节点
Button addButton = new Button("Add Node");
addButton.setOnAction(event -> {
// 获取当前选定的节点
TreeItem<String> selectedItem = treeView.getSelectionModel().getSelectedItem();
// 创建一个新的子节点
TreeItem<String> newItem = new TreeItem<>("New Node");
// 将新节点添加到选定节点的子节点列表中
selectedItem.getChildren().add(newItem);
// 展开选定节点
selectedItem.setExpanded(true);
});
// 创建编辑按钮,用于编辑选定节点的名称
Button editButton = new Button("Edit Node");
editButton.setOnAction(event -> {
// 获取当前选定的节点
TreeItem<String> selectedItem = treeView.getSelectionModel().getSelectedItem();
// 如果没有选定节点,则返回
if (selectedItem == null) {
return;
}
// 创建一个对话框,用于输入新节点名称
TextInputDialog dialog = new TextInputDialog(selectedItem.getValue());
dialog.setTitle("Edit Node");
dialog.setHeaderText(null);
dialog.setContentText("Enter new node name:");
// 显示对话框,等待用户输入
Optional<String> result = dialog.showAndWait();
// 如果用户输入了新名称,则将其保存到选定节点中
result.ifPresent(name -> selectedItem.setValue(name));
});
// 设置单元格工厂,用于更新节点名称
treeView.setCellFactory(TextFieldTreeCell.forTreeView());
// 创建BorderPane,将TreeView和按钮添加到其中
BorderPane root = new BorderPane();
root.setCenter(treeView);
// 创建VBox,将按钮添加到其中
VBox buttonBox = new VBox();
buttonBox.getChildren().addAll(addButton, editButton);
root.setRight(buttonBox);
// 创建场景
Scene scene = new Scene(root, 300, 250);
// 设置舞台标题并显示
primaryStage.setTitle("TreeView Example");
primaryStage.setScene(scene);
primaryStage.show();
// 添加监听器,在对话框关闭时输出JSON
primaryStage.setOnCloseRequest(event -> {
// 获取TreeView的根节点
TreeItem<String> rootNode = treeView.getRoot();
// 将根节点转换为Map
Map<String,Object> ans = toMap(rootNode);
// 输出JSON字符串
System.out.println(Json.toJson(ans));
});
}
private Map<String,Object> toMap(TreeItem<String> node) {
Map<String,Object> ans = new HashMap<>();
ans.put("name",node.getValue());
if (node.getChildren().size() > 0) {
List<Map<String,Object>> children = new ArrayList<>();
for (TreeItem<String> child : node.getChildren()) {
children.add(toMap(child));
}
ans.put("children", children);
}
return ans;
}
public static void main(String[] args) {
launch(args);
}
}
运行的结构为
融合SpringBoot的JavaFx方法
可见,标准的启动方法为创建一个Main函数进行处理,那么我们可以联想到,如果使用Springboot,该如何启动,下面是一个完整的使用Springboot创建Javafx桌面应用的方法
springboot启动类
@SpringBootApplication
public class AutoToolsApplication {
public static void main(String[] args) {
Application.launch(MainApp.class, args);
}
}
在Start函数中编写如下代码
@Override
public void start(Stage stage) throws Exception {
// 创建 Spring 应用程序上下文
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 注册一个配置类,以便 Spring 能够扫描和识别所有的 Bean
context.register(Config.class);
context.register(RestTemplateConfig2.class);
// context.register(ThreadPoolConfig.class);
// 启动 Spring 应用程序上下文
context.refresh();
stage.setTitle("效率工具");
HostServices hostServices = getHostServices();
MenuService functionMenuService = SpringContextUtil.getBean(MenuService.class);
MenuBar menuBar = new MenuBar(thingMenu(functionMenuService),
chatMenu(functionMenuService),
browserMenu(functionMenuService,hostServices),
logMenu(functionMenuService),
projectMenu(functionMenuService),
knowledgeMenu(functionMenuService),
scriptMenu(functionMenuService),
toolsMenu(functionMenuService),
buttMenu(functionMenuService),
networkToolsButton(functionMenuService),
reminderMenu(functionMenuService),
configurationMenu(functionMenuService),
loveMenu(functionMenuService),
knowledgeTreeMenu(functionMenuService,hostServices),
sidelineMenu(functionMenuService),
dataMenu(functionMenuService)
);
// 创建一个用于显示时钟的标签
Label clockLabel = new Label();
clockLabel.setFont(Font.font("Arial", FontWeight.BOLD, 48));
// 创建一个用于显示"慢"字的标签
Label slowLabel = new Label("沉心、平和、稳扎稳打");
slowLabel.setFont(Font.font("SimSun", FontWeight.BOLD, 48));
slowLabel.setTextFill(new Color(0f, 0f, 0f, 1));
slowLabel.setPrefWidth(800);
slowLabel.setAlignment(Pos.CENTER);
StackPane clockContainer = new StackPane();
StackPane.setAlignment(clockLabel, Pos.CENTER);
StackPane.setAlignment(slowLabel, Pos.TOP_CENTER);
clockContainer.getChildren().addAll(slowLabel, clockLabel);
BorderPane.setAlignment(clockContainer, Pos.CENTER);
BorderPane.setMargin(clockContainer, new Insets(150));
// 创建一个用于更新时钟的时间线程
Thread clockThread = new Thread(() -> {
while (true) {
Platform.runLater(() -> {
// 获取当前时间并设置到标签上
LocalDateTime currentTime = LocalDateTime.now();
String formattedTime = currentTime.format(DateTimeFormatter.ofPattern("HH:mm:ss"));
clockLabel.setText(formattedTime);
});
try {
// 等待1秒钟
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
clockThread.setDaemon(true);
clockThread.start();
BorderPane root = new BorderPane();
root.setTop(menuBar);
root.setCenter(clockContainer);
Scene scene = new Scene(root, 1920 * 0.6, 1080 * 0.6);
stage.setScene(scene);
stage.show();
}
简单梳理一下这段代码,首先,利用下面的代码,创建Springboot上下文,并注册两个配置,叫Config和RestTemplateConfig2
// 创建 Spring 应用程序上下文
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 注册一个配置类,以便 Spring 能够扫描和识别所有的 Bean
context.register(Config.class);
context.register(RestTemplateConfig2.class);
// context.register(ThreadPoolConfig.class);
// 启动 Spring 应用程序上下文
context.refresh();
然后在Config Bean的代码中加入@ComponentScan注解,那么整个应用的所有Bean都将被扫描并被spring上下文管理起来
@Configuration
@ComponentScan
public class Config {
}
然后,在后面的代码中,我们只需要像编写后端代码一样,编写桌面端程序即可。不需要额外学习任何的库或者技术