Java简易系统监视器system-monitoring系列:增加记忆功能

Java简易系统监视器system-monitoring:实时显示CPU使用率、内存使用率、电脑电池剩余电量、时间(时、分、秒)。创建系统托盘,设置系统托盘菜单,窗体置顶显示。通过jna调用dll文件读取电池数据。


目录

前言

技术点

核心代码

Properties.java

AppUtil.java

cxzgwing.Menu#setLayoutJMenu

cxzgwing.listener.FrameDragListener#mouseReleased

pom.xml

GitHub

Gitee

参考链接


前言

由于system-monitoring之前的版本是每次启动后会重置为默认布局,为了方便使用,特增加记忆功能。当修改布局、显示标签以及移动窗体位置之后,会记录修改后的状态,以便在下次启动时恢复该状态。

技术点

1、思路:每当修改布局、显示标签以及移动窗体位置之后,记录相关参数,写入配置文件。当创建窗体时,读取配置文件,根据配置参数设置窗体。若无配置文件,则置为默认布局。

2、增加了日志记录。

3、依赖:slf4j、logback、fastjson、lombok。

核心代码

Properties.java

package cxzgwing.model;

import java.util.HashMap;
import java.util.Map;

import com.alibaba.fastjson.annotation.JSONField;

import cxzgwing.utils.Constants;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;

@Data
@EqualsAndHashCode
@ToString
public class Properties {
    // 1-单列布局 2-双列布局(默认)
    @JSONField(name = "layout")
    private int layout;

    // 显示标签:1-CPU 2-Memory 3-Battery 4-Time 默认全选
    @JSONField(name = "display")
    private Map<String, Boolean> displayMap;

    @JSONField(name = "x")
    private int x;
    @JSONField(name = "y")
    private int y;

    public Properties() {
        this.layout = 2;
        // 窗体默认在屏幕右下角,x和y均设置为-1
        this.x = -1;
        this.y = -1;
        this.displayMap = new HashMap<>();
        this.displayMap.put(Constants.FIELD_CPU, true);
        this.displayMap.put(Constants.FIELD_MEMORY, true);
        this.displayMap.put(Constants.FIELD_BATTERY, true);
        this.displayMap.put(Constants.FIELD_TIME, true);
    }

    @JSONField(serialize = false, deserialize = false)
    public boolean isSingleLayout() {
        return this.layout == Constants.Single_Layout;
    }

    @JSONField(serialize = false, deserialize = false)
    public boolean isDoubleLayout() {
        return this.layout == Constants.Double_Layout;
    }

    @JSONField(serialize = false, deserialize = false)
    public boolean isCpuDisplay() {
        return this.displayMap.get(Constants.FIELD_CPU);
    }

    @JSONField(serialize = false, deserialize = false)
    public boolean isMemoryDisplay() {
        return this.displayMap.get(Constants.FIELD_MEMORY);
    }

    @JSONField(serialize = false, deserialize = false)
    public boolean isBatteryDisplay() {
        return this.displayMap.get(Constants.FIELD_BATTERY);
    }

    @JSONField(serialize = false, deserialize = false)
    public boolean isTimeDisplay() {
        return this.displayMap.get(Constants.FIELD_TIME);
    }

    @JSONField(serialize = false, deserialize = false)
    public void put(String name, boolean isDisplay) {
        this.displayMap.put(name, isDisplay);
    }

}

AppUtil.java

package cxzgwing.utils;

import java.awt.*;
import java.io.*;
import java.lang.management.ManagementFactory;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.sun.management.OperatingSystemMXBean;

import cxzgwing.Window;
import cxzgwing.dll.Dll;
import cxzgwing.model.Properties;

public class AppUtil {
    private static final Logger logger = LoggerFactory.getLogger(AppUtil.class);
    private static OperatingSystemMXBean systemMXBean;
    static {
        systemMXBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
    }

    public static String getTime() {
        return LocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss"));
    }

    public static String getMemoryLoad() {
        double totalPhysicalMemorySize = systemMXBean.getTotalPhysicalMemorySize();
        double freePhysicalMemorySize = systemMXBean.getFreePhysicalMemorySize();
        double value = freePhysicalMemorySize / totalPhysicalMemorySize;
        return "M: " + String.format("%.1f", (1 - value) * 100) + "%";
    }

    public static String getSystemCpuLoad() {
        return "C: " + String.format("%.1f", systemMXBean.getSystemCpuLoad() * 100) + "%";
    }

    public static String getBatteryPercent() {
        int value = 225;
        try {
            value = Dll.dll.BatteryPercent();
        } catch (Exception e) {
            logger.error("getBatteryPercent error", e);
        }
        return "B: " + value + "%";
    }

    public static void initWindowLocation(Window window, Properties properties) {

        // 获得窗体宽
        int windowWidth = window.getWidth();
        // 获得窗体高
        int windowHeight = window.getHeight();
        // 定义工具包
        Toolkit kit = Toolkit.getDefaultToolkit();
        // 获取屏幕的尺寸
        Dimension screenSize = kit.getScreenSize();
        // 获取屏幕的宽
        int screenWidth = screenSize.width;
        // 获取屏幕的高
        int screenHeight = screenSize.height;
        // 获取任务栏
        Insets screenInsets = kit.getScreenInsets(window.getGraphicsConfiguration());
        // 获取窗体边界位置
        int windowMaxX = screenWidth - windowWidth;
        int windowMaxY = screenHeight - windowHeight - screenInsets.bottom;
        window.setWindowMaxX(windowMaxX);
        window.setWindowMaxY(windowMaxY);
        // 设置窗体位置坐标
        int x;
        int y;
        int propertiesX = properties.getX();
        if (propertiesX > -1 && propertiesX <= windowMaxX) {
            x = propertiesX;
        } else {
            x = windowMaxX;
        }
        int propertiesY = properties.getY();
        if (propertiesY > -1 && propertiesY <= windowMaxY) {
            y = propertiesY;
        } else {
            y = windowMaxY;
        }

        // 设置窗口相对于指定组件的位置:置于屏幕的中央
        // frame.setLocationRelativeTo(null);

        // 设置窗体位置(默认在屏幕右下角)
        if (x != window.getX() || y != window.getY()) {
            window.setLocation(x, y);
        }
    }

    public static Properties getProperties() {
        Properties properties;
        String propertiesPath = getPropertiesPath();
        String content = readFile(propertiesPath);
        if (StringUtils.isBlank(content)) {
            properties = new Properties();
            writeFile(propertiesPath, properties, false);
        } else {
            properties = JSON.parseObject(content, Properties.class);
        }
        return properties;
    }

    public static String readFile(String path) {
        String value = "";
        FileReader fileReader = null;
        BufferedReader bufferedReader = null;
        try {
            File file = new File(path);
            if (file.exists()) {
                fileReader = new FileReader(file);
                bufferedReader = new BufferedReader(fileReader);
                StringBuilder stringBuilder = new StringBuilder();
                String s;
                while ((s = bufferedReader.readLine()) != null) {
                    stringBuilder.append(s);
                }
                value = stringBuilder.toString();
            }
        } catch (Exception e) {
            logger.error("readFile error, return empty string", e);
        } finally {
            closeResource(bufferedReader);
            closeResource(fileReader);
        }
        return value;
    }

    public static boolean writeFile(String filePath, Object o, boolean append) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(filePath, append);
            fos.write(JSON.toJSONString(o).getBytes());
            return true;
        } catch (Exception e) {
            logger.error("writeFile error", e);
            return false;
        } finally {
            closeResource(fos);
        }
    }

    private static void closeResource(Closeable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (Exception e) {
                logger.error("closeResource error", e);
            }
        }
    }

    public static String getPropertiesPath() {
        String folder = getCurrentFolder();
        return folder + "properties.conf";
    }

    /**
     * 获取程序当前所在的文件夹
     * 
     * @return eg:/E:/Projects/GitHub/MyProjects/system-monitoring/target/classes/
     */
    private static String getCurrentFolder() {
        String locationPath =
                AppUtil.class.getProtectionDomain().getCodeSource().getLocation().getPath();
        if (locationPath.toUpperCase().contains(".JAR")) {
            // 截取.JAR第一次出现前的字符串
            String StrPath = locationPath.substring(0, locationPath.toUpperCase().indexOf(".JAR"));
            // 获取jar包的上一层文件夹
            locationPath = StrPath.substring(0, StrPath.lastIndexOf(File.separator) + 1);
        } else if (locationPath.toUpperCase().contains(".EXE")) {
            String StrPath = locationPath.substring(0, locationPath.toUpperCase().indexOf(".EXE"));
            locationPath = StrPath.substring(0, StrPath.lastIndexOf(File.separator) + 1);
        }
        return locationPath;
    }

    public static GridLayout initLayout(int displayLabelCount, Properties properties,
            Window window) {
        GridLayout gridLayout = null;
        if (properties.isSingleLayout()) {
            // 单列布局
            window.setLayout(gridLayout = new GridLayout(displayLabelCount, 1));
            window.setSize(75, 20 * displayLabelCount);
        } else if (properties.isDoubleLayout()) {
            // 双列布局
            switch (displayLabelCount) {
                case 1:
                    window.setLayout(gridLayout = new GridLayout(1, 1));
                    window.setSize(75, 20);
                    break;
                case 2:
                    window.setLayout(gridLayout = new GridLayout(1, 2));
                    window.setSize(150, 20);
                    break;
                case 3:
                case 4:
                    window.setLayout(gridLayout = new GridLayout(2, 2));
                    window.setSize(150, 40);
                    break;
                default:
                    window.setLayout(gridLayout = new GridLayout(2, 2));
                    window.setSize(150, 40);
            }
        }
        return gridLayout;
    }
}

cxzgwing.Menu#setLayoutJMenu

 private void setLayoutJMenu() {
        JMenu layoutJMenu = new JMenu("布局");
        layoutJMenu.setFont(font);
        JMenuItem singleJMenuItem = new JMenuItem("单列布局");
        singleJMenuItem.setFont(font);
        singleJMenuItem.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                properties.setLayout(Constants.Single_Layout);
                AppUtil.writeFile(AppUtil.getPropertiesPath(), properties, false);
                window.setSize(85, 80);
                window.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 1));
                reloadWindow();
                AppUtil.initWindowLocation(window, properties);
                refreshWindow();
            }
        });
        JMenuItem doubleJMenuItem = new JMenuItem("双列布局");
        doubleJMenuItem.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                properties.setLayout(Constants.Double_Layout);
                AppUtil.writeFile(AppUtil.getPropertiesPath(), properties, false);
                window.setSize(150, 40);
                window.setLayout(new GridLayout(2, 2));
                reloadWindow();
                AppUtil.initWindowLocation(window, properties);
                refreshWindow();
            }
        });
        doubleJMenuItem.setFont(font);
        layoutJMenu.add(singleJMenuItem);
        layoutJMenu.add(doubleJMenuItem);
        jPopupMenu.add(layoutJMenu);
    }

cxzgwing.listener.FrameDragListener#mouseReleased

    @Override
    public void mouseReleased(MouseEvent e) {
        mouseDownCompCoords = null;
        if (this.windowMovable.isTrue()
                && (properties.getX() != window.getX() || properties.getY() != window.getY())) {
            properties.setX(window.getX());
            properties.setY(window.getY());
            try {
                AppUtil.writeFile(AppUtil.getPropertiesPath(), properties, false);
            } catch (Exception ex) {
                ex.printStackTrace();
                logger.error("mouseReleased error", ex);
            }
        }
    }

pom.xml

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

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cxzgwing</groupId>
    <artifactId>system-monitoring</artifactId>
    <version>2.1.0</version>

    <name>system-monitoring</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna -->
        <dependency>
            <groupId>net.java.dev.jna</groupId>
            <artifactId>jna</artifactId>
            <version>5.5.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
            <scope>provided</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.80</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.12.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.30</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>

    </dependencies>

    <build>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
                <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
                <plugin>
                    <artifactId>maven-site-plugin</artifactId>
                    <version>3.7.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-project-info-reports-plugin</artifactId>
                    <version>3.0.0</version>
                </plugin>
            </plugins>
        </pluginManagement>

        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>cxzgwing.App</mainClass>
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>assembly</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

GitHub

GitHub - cxzgwing/system-monitoring: Java Swing applet, real-time monitoring system CPU usage and memory usage.

Gitee

system-monitoring: Java Swing applet, real-time monitoring system CPU usage and memory usage.​​​​​​

参考链接

[1] 拼命三郎bai.JAVA 获取JAR包所在的文件夹.2014-12-11 22:26
https://www.cnblogs.com/MBai/p/4158646.html

[2] 凡心.Java Logging 日志框架 SLF4J 的使用(Maven).2020年06月09日 17:18
https://juejin.cn/post/6844904184492326926

[3] 疯狂哈丘.logback配置详解 & 原理介绍.2018-09-01 13:45:16
https://blog.csdn.net/u013332124/article/details/82286573

[4] 刚入门的小小白.addShutdownHook ---程序出错退出终极处理办法(转).2018-08-27 11:10:00
https://blog.csdn.net/qq_38238217/article/details/82109090

[5] 菜鸟教程.Fastjson 简明教程
https://www.runoob.com/w3cnote/fastjson-intro.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值