Java简易系统监视器system-monitoring:实时显示CPU使用率、内存使用率、电脑电池剩余电量、时间(时、分、秒)。创建系统托盘,设置系统托盘菜单,窗体置顶显示。通过jna调用dll文件读取电池数据。
目录
前言
技术点
核心代码
Properties.java
AppUtil.java
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;
}
}
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
|