利用Springboot来驱动开发桌面程序

news2024/11/29 2:48:18

众所周知,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 {
}

然后,在后面的代码中,我们只需要像编写后端代码一样,编写桌面端程序即可。不需要额外学习任何的库或者技术

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/528389.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python 的垃圾回收机制

一、 引入 python解释器在执行到定义变量的语法时&#xff0c;会申请内存空间来存放变量的值&#xff0c;而内存的容量是有限的&#xff0c;这就涉及到变量值所占用内存空间的回收问题&#xff0c;当一个变量值没有用了&#xff08;简称垃圾&#xff09;就应该将其占用的内存给…

【Linux】IO多路转接-poll

文章目录 I/O多路转接-pollpoll初识poll函数poll的小测试-监控标准输入poll服务器poll_server.cc poll的优点poll的缺点 I/O多路转接-poll poll初识 poll也是系统提供的一个多路转接接口, poll系统调用也可以让我们的程序同时监视多个文件描述符上的事件是否就绪,和select的定…

DDos攻击概述

1.def&#xff1a; 通过大规模互联网流量淹没目标服务器或其周边基础设施&#xff0c;以破坏目标服务器、服务或网络正常流量的恶意行为 目标服务器类比作商店&#xff1b; 网络的正常流量类比作顾客&#xff1b; 此恶意行为便相当于让一堆小混混装成正常顾客涌入商店&…

软件自动化测试有什么优势?自动化测试框架有哪些?

一、 软件自动化测试的优势 在软件测试过程中&#xff0c;自动化测试不断被提高到更高的级别&#xff0c;以提高测试效率以及降低测试成本。 1.节省时间和成本 手动测试需要耗费大量的时间和精力&#xff0c;而自动化测试可以在较短时间内执行多次测试&#xff0c;并且可以在…

Alibaba Sentinel整合SpringBoot,为微服务保驾护航!

前言 随着微服务的流行&#xff0c;服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件&#xff0c;主要以流量为切入点&#xff0c;从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来…

08-05 应用层设计

伸缩性的架构设计——服务器集群的伸缩性 DNS负载均衡 DNS服务器将访问的域名转发到对应的网关&#xff0c;网关层做反向代理。 利用消息组件对业务场景进行解耦 适合用消息组件解耦的场景 长任务&#xff08;时间长&#xff0c;逻辑复杂&#xff0c;可异步&#xff09…

React Antv G2Plot 「指标拆解图」 前端可视化实战 实现渲染、重置、筛选功能

背景 实现对指定数据的「指标拆解图」 渲染&#xff0c;并且可以根据筛选项进行变化。 任务分解 antv 的图表&#xff0c;以及请求后端的载荷对传入的数据结构有严格要求 一个工具函数将后端接口返回的数据格式化成 antv 图表要求的格式一个工具函数将前端提交的请求数据格…

Copilot入门

文章目录 简介安装初试快捷键取消订阅参考文献 简介 Copilot 是一款 GitHub 和 OpenAI 合作开发的 AI 结对编程工具&#xff0c;支持 Visual Studio、Neovim、VS Code、JetBrains IDEs&#xff0c;用于自动补全代码。 本文以 Python PyCharm 为例。 安装 GitHub Copilot&am…

【数据结构】栈及其实现

目录 &#x1f920;前言 什么是栈&#xff1f; 栈的定义及初始化 栈的定义 栈的初始化 栈的判空 栈顶压栈 栈顶出栈 栈的数据个数 栈的销毁 完整代码 总结 &#x1f920;前言 学了相当长一段时间的链表&#xff0c;总算是跨过了一个阶段。从今天开始我们将进入栈和…

什么是AIGC

AIGC是人工智能创意生成的缩写&#xff08;Artificial Intelligence Generated Creativity&#xff09;&#xff0c;指的是利用人工智能技术实现的创意生成。通俗来说&#xff0c;就是让机器产生新颖、独特且有创造性的作品或方案&#xff0c;例如音乐、绘画、视频、文本等等。…

Sui基金会宣布面向APAC的Office Hours计划

诚挚邀请构建者与Sui基金会的Growth团队一起开启“Office Hours”计划&#xff0c;共同努力&#xff0c;迈向业务增长的下一步。 Sui基金会致力于推动Sui在全球范围内的普及。为此&#xff0c;我们通过积极支持开发人员的开发者资助计划、Builder House和大使计划在Sui上开始…

如何高效运行Omniverse,无惧本地硬件压力

无论是创造能够表达原始情感的逼真数字人&#xff0c;还是构建身临其境的虚拟世界&#xff0c;全球设计、工程、创意和其他行业的人士都在通过3D工作流&#xff0c;突破技术壁垒并拓展创意可能&#xff0c;让虚拟世界和现实世界交融与观众产生共鸣。 而在众多连接未来创作内容的…

ES6中函数新增的方式方法

1.1函数形参的默认值 1.1.1基本用法 ES6 之前&#xff0c;不能直接为函数的参数指定默认值&#xff0c;只能采用变通的方法。如下代码&#xff1a; function func(x,y){y y || "tom";console.log(x,y);}func("hello"); //hello tomfunc("…

数据库标准化之核心结局变量集(COS)

COS介绍 核心结果集&#xff08;COS&#xff09;是在特定健康状况下进行的所有临床试验中应测量和报告的一组最少结局变量集。COS数据库是这些变量集的集合&#xff0c;这些集合是通过循证和迭代过程开发的。该数据库由COMET倡议维护&#xff0c;该计划是研究人员&#xff0c;…

Linux 系统上 C 程序的编译与调试 2 总结

1.gcc分布编译链接 &#xff08;1) 预编译 : gcc -E main.c -o main.i (2) 编译&#xff1a; gcc -S main.i -o main.s (3) 汇编&#xff1a; gcc -c main.s -o main.o (4) 链接&#xff1a; gcc main.o -o main gcc -E hello.c -o hello.i #预处理 gcc -S hello.i -o h…

【FMC134】ADC12DJ3200之4通道3.2GSPS(2 通道6.4GSPS) 12 位AD高速采集子卡设计原理图及调试经验

板卡概述 FMC134 是一款4 通道3.2GSPS&#xff08;或者配置成2 通道6.4GSPS&#xff09;采样率的12 位AD 采集FMC子卡模块&#xff0c;该板卡为FMC标准&#xff0c;符合VITA57.4 规范&#xff0c;可以作为一个理想的IO 模块耦合至FPGA 前端&#xff0c;射频模拟信号数字化后通过…

【多线程进阶一】常见的锁策略

目录 一、常见的锁策略 &#x1f345;1、常见的锁策略 &#x1f345;2、Synchronized实现了哪些锁策略&#xff1f; &#x1f345;3、自旋锁的实现方式—CAS &#xff08;1&#xff09;CAS伪代码 &#xff08;2&#xff09;演示 使用CAS方式来实现自增操作&#xff1a; &am…

Linux 系统修改环境变量的方法

1. Linux 系统修改环境变量 正常情况下改变环境变量可以修改的文件有两类&#xff1a; 第一类是 “系统的全局环境变量”&#xff0c;修改之后可作用于整个系统包含的所有用户都会生效&#xff1b;(文件&#xff1a;/etc/profile) 第二类是 “局部环境变量”&#xff0c;也就…

Linux C程序多文件编译

C程序多文件编译 在Linux平台C编程&#xff0c;实现求两数最大值和两数之和的功能 1.编写add.c wysDESKTOP-2OU3HRV:~/mycode/day02$ vi add.c1 int add(int x,int y)2 {3 return x y;4 } 2.编写头文件add.h wysDESKTOP-2OU3HRV:~/mycode/day02$ vi add.hint add(…

Python 实验五 字符串与正则表达式

1.输入一个字符串&#xff0c;将该字符串中下标为偶数的字符组成新串并通过字符串格式化方式显示。 a input("请输入一个字符串&#xff1a;") b a[1::2] print("老串为&#xff1a;%a&#xff0c;新串为&#xff1a;%a"%(a,b))2.编写程序&#xff0c;生…