javaFx 系统最小化托盘(及其避坑)、开机自启动

news2024/12/28 22:18:19

1、系统最小化托盘

参考资料:

https://blog.51cto.com/u_14191/6310480

javafx 设置最小窗口大小 - Java (1) - 芒果文档

注意事项

1.直接使用第一个参考资料中的MinWindow类即可。

#最小化托盘 -- 一般放置在 start(Stage stage)处
MinWindow.getInstance().listen(stage);

#隐藏最小化托盘 -- 一般放置在关闭窗口按钮的controller方法处
MinWindow.getInstance().hide(stage);

2.图片链接,我的放在了这个路径下

/img/icon.png

3. 配置pom文件

<!--系统最小托盘参数,此参数必须, 空格及后面的-xmx是设置内存大小的,可以不用--> 
<vmArgs>-Djava.awt.headless=false -Xmx1024m</vmArgs>

<!--可直接使用, 这个是为了让系统支持系统托盘,因为默认是true-->
<vmArgs>-Djava.awt.headless=false</vmArgs>
<build>
        <plugins>
            <plugin>
               ....
            </plugin>
            <plugin>
                <groupId>io.github.fvarrui</groupId>
                <artifactId>javapackager</artifactId>
                <version>1.7.5</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>package</goal>
                        </goals>
                        <configuration>
                            <!-- 程序入口 -->
                            <mainClass>cn.xxx.xxxApplication</mainClass>
                            <!-- 打包Jre -->
                            <bundleJre>true</bundleJre>
                            <!--系统最小托盘参数,此参数必须-->
                            <vmArgs>-Djava.awt.headless=false -Xmx1024m</vmArgs>
                            <!-- admin 权限检查-->
                            <administratorRequired>true</administratorRequired>
                            <platform>windows</platform>
                            <!-- 设置Jre路径 -->
                            <jrePath>C:\Program Files (x86)\Java\jre\jre</jrePath>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

4、系统最小化托盘后,创建桌面快捷方式后,点击快捷方式或.exe,发现会重复打开多个窗口。

解决方法:
 

    private Stage primaryStage;
    // 通信用
    private static ServerSocket socket;
    private static final int PORT = 9999;    
    private static final String REGISTRY_KEY = "Software\\Microsoft\\Windows\\CurrentVersion\\Run";
    private static final String APP_NAME = "xxx程序";

    /**
     * 加载页面
     *
     * @param stage 页面根对象
     * @throws IOException 加载异常
     */
    @Override
    public void start(Stage stage) throws IOException {
        // 尝试绑定端口
        if (!lockInstance()) {
            // 使用socket发送信号显示窗口
            sendShowWindowSignal();
            // 阻止当前程序开启
            System.exit(0);
        }
        

        primaryStage = stage;
        try {
            MinWindow.getInstance().listen(stage);
        }catch (Exception e){
            e.printStackTrace();
        }
        // 展示文件选择页面
        fileSelectPageShow(stage);
        // 启动一个线程进行监听
        new Thread(this::startServer).start();
    }

    // 尝试绑定端口
    private static boolean lockInstance() {
        try {
            socket = new ServerSocket(PORT); // 替换为你选择的端口
            return true;
        } catch (IOException e) {
            return false;
        }
    }
    // 使用socket发送信号显示窗口
    private static void sendShowWindowSignal(){
        try (Socket clientSocket = new Socket("localhost", PORT);
             DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream()))         
    {
            out.writeUTF("SHOW_WINDOW");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    // 启动监听程序
    private void startServer() {
        try {
            while (true) {
                try (Socket clientSocket = socket.accept();
                     DataInputStream in = new DataInputStream(clientSocket.getInputStream())) {
                    String command = in.readUTF();
                    if ("SHOW_WINDOW".equals(command)) {
                        Platform.runLater(this::showAndFocusStage);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

// 显示窗口并置顶程序
private void showAndFocusStage() {
        if (primaryStage.isIconified()) {
            primaryStage.setIconified(false);
        }
        if (!primaryStage.isShowing()) {
            primaryStage.show();
        }
        primaryStage.toFront();
        primaryStage.setAlwaysOnTop(true); // 临时置顶以确保窗口显示在前面
        primaryStage.setAlwaysOnTop(false); // 取消置顶
    }
// 当窗口真正退出关闭时,将socket关闭
 private static void unlockInstance() {
        try {
            if (socket != null && !socket.isClosed()) {
                socket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
// 启动窗口程序
 private void fileSelectPageShow(Stage stage) throws IOException {
        // 这个是窗口页面
        FXMLLoader loa = new FXMLLoader(Objects.requireNonNull(getClass().getClassLoader().getResource("fxml/xxxxx.fxml")));

        Parent root = loa.load();

        // 给Controller赋值根节点
        ConventionalMeteorologySettingController npc = loa.getController();
        npc.setStage(stage);

        stage.setTitle("xxx程序");
        // 窗口关闭监听
        stage.setOnCloseRequest(event -> unlockInstance());
        stage.setScene(new Scene(root, 800.0, 600));

        // 设置窗口样式,去掉最小化、最大化、关闭按钮
        stage.initStyle(StageStyle.UNDECORATED);

        // 添加拖动事件监听器
        root.setOnMousePressed(event -> {
            xOffset = event.getSceneX();
            yOffset = event.getSceneY();
        });

        root.setOnMouseDragged(event -> {
            stage.setX(event.getScreenX() - xOffset);
            stage.setY(event.getScreenY() - yOffset);
        });
        stage.show();
        // 这个是controller中的一个方法(当程序启动时去执行)
        npc.initFilePath();
    }

2、开机自启动

// 开机自启程序 -- 其实就是利用程序向注册表中注册,电脑开机后会检查注册表的
 public static void setStartup(boolean enable) {
        String exePath = new File(PathUtils.getExecutablePath(), "xxx程序.exe").getAbsolutePath();
        String command = "\"" + exePath + "\"";
        if (enable) {
            Advapi32Util.registrySetStringValue(WinReg.HKEY_CURRENT_USER, REGISTRY_KEY, APP_NAME, command);
        } else {
            Advapi32Util.registryDeleteValue(WinReg.HKEY_CURRENT_USER, REGISTRY_KEY, APP_NAME);
        }
    }

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

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

相关文章

鸿蒙仓颉语言【cryptocj 库】(介绍与SHA、MD5、HMAC摘要算法)

cryptocj 库 介绍 cryptocj 是一个安全的密码库&#xff0c;包括常用的密码算法、常用的密钥生成和签名验证。 该库是对 C 语言的 openSSL 封装的仓颉加密算法 1 提供SHA、MD5、HMAC摘要算法。 前置条件&#xff1a;NA 场景&#xff1a; OHOS&#xff0c; Linux&#xff…

昇思25天学习打卡营第17天 | CycleGAN图像风格迁移互换

通过深入学习CycleGAN模型&#xff0c;我对无监督图像到图像的转换技术有了更深的理解。CycleGAN不仅能在没有成对训练样本的情况下实现域之间的转换&#xff0c;而且在保持内容结构的同时成功转换图像风格&#xff0c;这在许多应用中都非常有用&#xff0c;如艺术风格转换、季…

C++树(二)【直径,中心】

目录&#xff1a; 树的直径&#xff1a; 树的直径的性质&#xff1a; 性质1&#xff1a;直径的端点一定是叶子节点 性质2&#xff1a;任意点的最长链端点一定是直径端点。 性质3&#xff1a;如果一棵树有多条直径,那么它们必然相交&#xff0c;且有极长连…

Linux搭建Kubernetes集群(单Master)【附图文】

文章目录 一、集群环境配置要求二、主机准备三、初始环境准备1.关闭防火墙2.关闭 selinux3.关闭swap4.加载 br_netfilter 模块5.允许iptables转发流量6.设置时间同步 四、安装Docker五、安装kubeadm, kubectl, kubelet六、在Master节点部署集群七、将 node 节点加入集群八、部署…

springcloud rocketmq 新增的消费者组从哪里开始消费

如果新建一个新的消费者组&#xff0c;是否会消费历史消息&#xff0c;导致重复消费&#xff1f; 直接在 console 界面新增消费者组&#xff0c;但是没有办法绑定订阅关系&#xff0c;没有找到入口&#xff0c;在 控制台项目源码 rocketmq-externals 也没有找到可以确定订阅关系…

Windows 11预览补丁KB5040527影响火绒驱动加载的解决办法

7 月 11 日&#xff0c;微软更新Windows 11 预览版本补丁 KB5040527&#xff0c;补丁安装后会影响火绒驱动加载导致火绒安全软件服务异常&#xff0c;补丁相关信息如下&#xff1a; https://blogs.windows.com/windows-insider/2024/07/11/releasing-windows-11-builds-22621-…

微信视频号下载又一工具,免费简单易用!

Res-downloader嗅探资源下载器请收好 官方称支持微信视频号、抖音、快手、小红书等网络资源下载 使用方法 第一步&#xff0c;下载软件 文末扫码 或者搜索关注公众号AIshape 回复 RES 获取 或 自行百度搜索下载 第二步&#xff0c;软件设置 打开软件会弹出接受传入网络链…

CSI-RS在信道中传输的过程

简单介绍CSI-RS信号生成&#xff0c;在信道中传输和接收的过程 1.载波配置 首先需要配置载波相关的参数 系统带宽和子载波间隔 5G NR中&#xff0c;系统带宽和子载波间隔是两个关键参数&#xff0c;共同决定无线资源的分配和使用 系统带宽 5G NR支持广泛的系统带宽&…

【SOC 芯片设计 DFT 学习专栏 -- DFT OCC 与 ATPG的介绍】

请阅读【嵌入式及芯片开发学必备专栏】 请阅读【芯片设计 DFT 学习系列 】 如有侵权&#xff0c;请联系删除 转自&#xff1a; 简矽芯学堂 简矽芯学堂 2024年01月18日 09:00 陕西 文章目录 OCC 介绍Fast ScanFull chip ATPGPartition ATPGHierarchical ATPG OCC 介绍 OCC&am…

Ubuntu下载jdk:cannot execute binary file

虚拟机上Ubuntu系统安装jdk且配置环境之后&#xff0c;java -version显示cannot execute binary file&#xff0c;多番查阅推测是由于系统和jdk版本不兼容的原因。 uname -m查看系统版本位i686&#xff0c;是32位的&#xff0c;和64位的jdk版本不兼容。因此&#xff0c;下载32位…

QT--进程

一、进程QProcess QProcess 用于启动和控制外部进程&#xff0c;管理其输入输出流。 使用方法 start()&#xff1a;启动一个新进程。setStandardInputFile()&#xff1a;将文件作为标准输入。将进程的标准输入&#xff08;stdin&#xff09;重定向到指定的文件。换句话说&am…

【Linux】从零开始认识多线程 --- 线程互斥

人生有许多事情 正如船后的波纹 总要过后才觉得美的 -- 余光中 线程互斥 1 线程类的封装1.1 框架搭建1.2 线程启动1.3 线程终止1.4 线程等待1.5 运行测试 2 线程互斥2.1 多线程访问的问题2.2 解决办法 --- 锁2.3 从原理角度理解锁 Thanks♪(&#xff65;ω&#xff65;)&am…

QT信号和信号槽

信号和信号槽 一.信号与槽1.信号和槽的概述1.2.信号的本质1.3.信号的本质 二.信号和槽的使用2.1 连接信号和槽connect()函数原型&#xff1a;参数的说明 三.自定义信号和槽3.1基本语法1.自定义信号槽的书写规范2、自定义槽函数书写规范3.发送信号 3.2带参数的信号和槽 四.信号与…

Eclipse 搭建 C/C++ 开发环境以及eclipse的使用

一、下载、安装 MinGW 1、下载: 下载地址&#xff1a;MinGW - Minimalist GNU for Windows - Browse Files at SourceForge.net 点击“Download Latest Version”即可 下载完成后&#xff0c;得到一个名为 mingw-get-setup.exe 的安装文件。双击运行&#xff0c;安装即可。 …

一套功能齐全、二开友好的即时通讯IM工具,提供能力库和UI库,支持单聊、频道和机器人(附源码)

前言 在当今数字化时代&#xff0c;即时通讯(IM)和实时音视频(RTC)功能已成为众多应用的标配。然而&#xff0c;现有的解-决方案往往存在一些痛点&#xff0c;如架构落后、成本高昂、数据安全性和隐私保护不足&#xff0c;以及二次开发和部署的复杂性。 为了解决这些问题&…

超薄超小单独北斗定位的4G工牌记录仪、4G胸卡记录仪

AIoT万物智联&#xff0c;智能安全帽生产厂家&#xff0c;执法记录仪生产厂家&#xff0c;智能安全帽、智能头盔、头盔记录仪、执法记录仪、智能视频分析/边缘计算AI盒子、车载DVR/NVR、布控球、智能眼镜、智能手电、智能电子工牌、无人机4G补传系统等统一接入大型融合通信可视…

无法继续安装 计算机正忙于安装一个非 Visual Studio 的程序。

解决办法 以管理员身份打开cmd运行窗口&#xff0c;执行以下命令&#xff1a; taskkill -f -im msiexec*

网络三剑客之sed

目录 一、sed是什么 二、sed为什么这样工作&#xff08;原理&#xff09; 三、sed命令该怎么操作 3.1 基本的操作选项 3.2 怎么去使用sed 3.3 操作实例 3.3.1 打印输出&#xff08;-n、-p、-r&#xff09; 3.3.2 增加内容&#xff08;i、a&#xff09; 3.3.3 删除&…

网络安全入门教程(非常详细)从零基础入门到精通_网路安全 教程

前言 1.入行网络安全这是一条坚持的道路&#xff0c;三分钟的热情可以放弃往下看了。2.多练多想&#xff0c;不要离开了教程什么都不会了&#xff0c;最好看完教程自己独立完成技术方面的开发。3.有时多百度&#xff0c;我们往往都遇不到好心的大神&#xff0c;谁会无聊天天给…

机器学习 | 回归算法原理——最速下降法(梯度下降法)

Hi&#xff0c;大家好&#xff0c;我是半亩花海。接着上次的最小二乘法继续更新《白话机器学习的数学》这本书的学习笔记&#xff0c;在此分享最速下降法&#xff08;梯度下降法&#xff09;这一回归算法原理。本章的回归算法原理基于《基于广告费预测点击量》项目&#xff0c;…