Java简易系统监视器system-monitoring:实时显示CPU使用率、内存使用率、笔记本电脑电池剩余电量、时间(时、分、秒)。创建系统托盘,设置系统托盘菜单,窗体置顶显示。通过jna调用dll文件读取电池数据。
目录
效果图
功能说明
- Java简易系统监视器system-monitoring:实时显示CPU使用率、内存使用率、笔记本电脑电池剩余电量、时间(时、分、秒)。CPU使用率、内存使用率和时间每秒更新一次,笔记本电脑电池剩余电量每15秒更新一次。
- 创建系统托盘,设置系统托盘菜单,窗体置顶显示。
- 系统托盘按钮:
- 移动(或固定):点击后可移动或固定窗体。
- 刷新:点击可刷新窗体,当窗体显示异常时可使用。
- 布局:可更改窗体布局,可选“单列布局”、“双列布局”。(效果图为双列布局)
- 显示:可选择需要显示的参数,可勾选“CPU”、“内存”、“电量”、“时间”。
- 退出程序:点击可退出程序。
- 窗体不可移动至屏幕外。
- 窗体大小可根据显示的参数个数自动适配。
- 点击系统托盘后,弹出多级菜单,当鼠标点击非菜单区域,弹出的多级菜单会自动消失。(基于JFrame+JPopupMenu实现)
项目与工具
Maven、Java 8、Swing、maven-assembly-plugin(jar-with-dependencies)、jna、dll
项目说明
- 使用jna调用C++生成的动态链接库dll文件监控电池剩余电量。
- 生成的system-monitoring-2.0.0-jar-with-dependencies.jar需与resources中的images文件夹和BatteryMonitor.dll文件同级。(与代码中读取相关文件路径的写法有关)
目录结构
核心代码
由于代码较多,此处就不全部贴出来了,需要完整代码的小伙伴请移步GitHub或Gitee。
Window.java
package cxzgwing;
import java.awt.*;
import java.time.Clock;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import cxzgwing.judgement.WindowMovable;
import cxzgwing.label.impl.BatteryLabel;
import cxzgwing.label.impl.CpuLabel;
import cxzgwing.label.impl.MemoryLabel;
import cxzgwing.label.impl.TimeLabel;
import cxzgwing.listener.FrameDragListener;
import cxzgwing.listener.TrayIconMouseListener;
import cxzgwing.task.BatteryMonitorTask;
import cxzgwing.task.CpuMemoryTimeMonitorTask;
import cxzgwing.task.GCTask;
import cxzgwing.utils.AppUtil;
import cxzgwing.utils.LabelLayout;
import cxzgwing.utils.ThreadUtil;
public class Window extends JFrame {
private Menu menu;
private WindowMovable windowMovable;
private CpuLabel cpuLabel;
private MemoryLabel memoryLabel;
private BatteryLabel batteryLabel;
private TimeLabel timeLabel;
private Font font;
private EmptyBorder emptyBorder;
private GridLayout gridLayout;
// 1-单列布局,2-双列布局
private int labelLayout;
// 窗体位置最大横坐标
private int windowMaxX;
// 窗体位置最大纵坐标
private int windowMaxY;
public Window() throws Exception {
// 初始化窗体是否可移动
windowMovable = new WindowMovable(false);
font = new Font("黑体", Font.PLAIN, 16);
labelLayout = LabelLayout.DOUBLE;
// 设置显示标签边距
emptyBorder = new EmptyBorder(0, 5, 0, 0);
// 设置布局
gridLayout = new GridLayout(2, 2);
// 初始化窗体
initWindow();
// 设置CPU使用率显示标签
initCpuJLabel();
// 内存使用率显示标签
initMemJLabel();
// 电池电量百分比显示标签
initBatteryJLabel();
// 时间显示标签
initTimeJLabel();
// 初始化托盘菜单
initMenu();
// 设置窗体是否可移动监听
setWindowDragListener();
// 添加窗体状态监听,使窗体一直显示
setWindowAlwaysShow();
// 添加系统托盘
setSystemTray();
// 显示
this.setVisible(true);
// 监控
monitoring();
}
private void initMenu() {
menu = new Menu(this, windowMovable, cpuLabel, memoryLabel, batteryLabel, timeLabel);
}
/**
* 初始化窗体,显示CPU使用率和Mem使用率
*/
private void initWindow() {
// 隐藏任务栏图标
this.setType(JFrame.Type.UTILITY);
// 设置窗口置顶
this.setAlwaysOnTop(true);
// 设置无边框
this.setUndecorated(true);
// 设置背景色
this.setBackground(new Color(0, 0, 0, 80));
// 设置窗体大小
this.setSize(150, 40);
// 设置布局
this.setLayout(gridLayout);
AppUtil.initWindowLocation(this);
}
private void setWindowDragListener() {
// 设置鼠标监听,可通过鼠标移动窗体位置
// 通过系统托盘菜单中的第一个按钮(移动 / 固定)来控制是否能移动窗体
FrameDragListener frameDragListener = new FrameDragListener(this, windowMovable);
this.addMouseListener(frameDragListener);
this.addMouseMotionListener(frameDragListener);
}
private void initTimeJLabel() {
// 时间显示标签
timeLabel = new TimeLabel(AppUtil.getTime());
timeLabel.setFont(font);
timeLabel.setForeground(Color.WHITE);
timeLabel.setBorder(emptyBorder);
gridLayout.addLayoutComponent("timeLabel", timeLabel);
this.add(timeLabel);
}
private void initBatteryJLabel() {
// 电池电量百分比显示标签
batteryLabel = new BatteryLabel(AppUtil.getBatteryPercent());
batteryLabel.setFont(font);
batteryLabel.setForeground(Color.WHITE);
batteryLabel.setBorder(emptyBorder);
gridLayout.addLayoutComponent("batteryLabel", batteryLabel);
this.add(batteryLabel);
}
private void initMemJLabel() {
// 内存使用率显示标签
memoryLabel = new MemoryLabel(AppUtil.getMemoryLoad());
memoryLabel.setFont(font);
memoryLabel.setForeground(Color.WHITE);
memoryLabel.setBorder(emptyBorder);
gridLayout.addLayoutComponent("memoryLabel", memoryLabel);
this.add(memoryLabel);
}
private void initCpuJLabel() {
// CPU使用率显示标签
cpuLabel = new CpuLabel(AppUtil.getSystemCpuLoad());
cpuLabel.setFont(font);
cpuLabel.setForeground(Color.WHITE);
cpuLabel.setBorder(emptyBorder);
gridLayout.addLayoutComponent("cpuLabel", cpuLabel);
this.add(cpuLabel);
}
/**
* 监控
*/
private void monitoring() {
ThreadUtil.addTask(new CpuMemoryTimeMonitorTask(cpuLabel, memoryLabel, timeLabel));
ThreadUtil.addTask(new BatteryMonitorTask(batteryLabel));
ThreadUtil.addTask(new GCTask());
}
/**
* 添加系统托盘
*/
private void setSystemTray() throws Exception {
try {
if (SystemTray.isSupported()) {
// 获取当前平台的系统托盘
SystemTray tray = SystemTray.getSystemTray();
// 加载一个图片用于托盘图标的显示
Image image = Toolkit.getDefaultToolkit()
.getImage(Clock.class.getResource("/images/system-monitoring-icon.png"));
// 创建点击图标时的弹出菜单方案三:JFrame + JPopupMenu
TrayIcon trayIcon = new TrayIcon(image, "System Monitoring");
trayIcon.addMouseListener(new TrayIconMouseListener(menu));
// 托盘图标自适应尺寸
trayIcon.setImageAutoSize(true);
// 添加托盘图标到系统托盘
tray.add(trayIcon);
} else {
throw new Exception("当前系统不支持系统托盘");
}
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
/**
* 添加窗体状态监听,使窗体一直显示
*/
private void setWindowAlwaysShow() {
this.addWindowStateListener(e -> {
int newState = e.getNewState();
if (JFrame.ICONIFIED == newState) {
this.setState(JFrame.NORMAL);
}
});
}
public void setWindowMaxX(int windowMaxX) {
this.windowMaxX = windowMaxX;
}
public void setWindowMaxY(int windowMaxY) {
this.windowMaxY = windowMaxY;
}
public int getWindowMaxX() {
return this.windowMaxX;
}
public int getWindowMaxY() {
return this.windowMaxY;
}
public int getLabelLayout() {
return labelLayout;
}
public void setLabelLayout(int labelLayout) {
this.labelLayout = labelLayout;
}
}
Menu.java
package cxzgwing;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Objects;
import javax.swing.*;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import cxzgwing.judgement.WindowMovable;
import cxzgwing.label.LabelAdaptor;
import cxzgwing.label.impl.BatteryLabel;
import cxzgwing.label.impl.CpuLabel;
import cxzgwing.label.impl.MemoryLabel;
import cxzgwing.label.impl.TimeLabel;
import cxzgwing.utils.AppUtil;
import cxzgwing.utils.LabelLayout;
public class Menu {
private JFrame jFrame;
private JPopupMenu jPopupMenu;
private Font font;
private Window window;
private WindowMovable windowMovable;
private CpuLabel cpuLabel;
private MemoryLabel memoryLabel;
private BatteryLabel batteryLabel;
private TimeLabel timeLabel;
private static final int WIDTH = 75;
private static final int HEIGHT = 110;
public Menu(Window window, WindowMovable windowMovable, CpuLabel cpuLabel,
MemoryLabel memoryLabel, BatteryLabel batteryLabel, TimeLabel timeLabel) {
this.window = window;
this.windowMovable = windowMovable;
this.cpuLabel = cpuLabel;
this.memoryLabel = memoryLabel;
this.batteryLabel = batteryLabel;
this.timeLabel = timeLabel;
this.font = new Font("宋体", Font.PLAIN, 13);
init();
addJPopupMenuListener();
}
private void hiddenFrameIfShowing() {
if (jFrame.isShowing()) {
jFrame.setVisible(false);
}
}
private void hiddenJPopupMenuIfShowing() {
if (jPopupMenu.isShowing()) {
jPopupMenu.setVisible(false);
}
}
private void addJPopupMenuListener() {
jPopupMenu.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
hiddenFrameIfShowing();
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {}
});
}
private void init() {
setJFrame();
setJPopupMenu();
}
private void setJPopupMenu() {
jPopupMenu = new JPopupMenu();
jPopupMenu.setSize(WIDTH, HEIGHT);
setMovableJMenu();
setRefreshJMenu();
setLayoutJMenu();
setDisplayJMenu();
setExitJMenu();
}
private void setExitJMenu() {
JMenuItem exitJMenuItem = new JMenuItem("退出程序");
exitJMenuItem.setFont(font);
exitJMenuItem.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
System.exit(0);
}
});
jPopupMenu.add(exitJMenuItem);
}
private void setDisplayJMenu() {
JMenu displayJMenu = new JMenu("显示");
displayJMenu.setFont(font);
JCheckBox cpuJCheckBox = new JCheckBox("CPU");
cpuJCheckBox.setFont(font);
cpuJCheckBox.setSelected(true);
cpuJCheckBox.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
stateChange(cpuLabel, cpuJCheckBox.isSelected());
}
});
JCheckBox memoryJCheckBox = new JCheckBox("内存");
memoryJCheckBox.setFont(font);
memoryJCheckBox.setSelected(true);
memoryJCheckBox.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
stateChange(memoryLabel, memoryJCheckBox.isSelected());
}
});
JCheckBox batteryJCheckBox = new JCheckBox("电量");
batteryJCheckBox.setFont(font);
batteryJCheckBox.setSelected(true);
batteryJCheckBox.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
stateChange(batteryLabel, batteryJCheckBox.isSelected());
}
});
JCheckBox timeJCheckBox = new JCheckBox("时间");
timeJCheckBox.setFont(font);
timeJCheckBox.setSelected(true);
timeJCheckBox.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
stateChange(timeLabel, timeJCheckBox.isSelected());
}
});
displayJMenu.add(cpuJCheckBox);
displayJMenu.add(memoryJCheckBox);
displayJMenu.add(batteryJCheckBox);
displayJMenu.add(timeJCheckBox);
jPopupMenu.add(displayJMenu);
}
private void stateChange(LabelAdaptor label, boolean isSelected) {
// 在复选框除按下鼠标,移除复选框区域后松开鼠标,此时复选框状态不变,无需操作
if ((label.isDisplay() && isSelected) || (!label.isDisplay() && !isSelected)) {
return;
}
label.setDisplay(isSelected);
windowRemoveAll();
reloadWindow();
refreshWindow();
}
private void reloadWindow() {
int count = getDisplayLabelCount();
GridLayout gridLayout = updateWindowLabelLayout(count);
reloadLabel(gridLayout);
}
private void reloadLabel(GridLayout gridLayout) {
// 由于不显示标签时,不读取相关数据,所以重新显示时需要更新数据
if (cpuLabel.isDisplay()) {
cpuLabel.setText(AppUtil.getSystemCpuLoad());
if (LabelLayout.DOUBLE == window.getLabelLayout() && !Objects.isNull(gridLayout)) {
gridLayout.addLayoutComponent("cpuLabel", cpuLabel);
}
window.add(cpuLabel);
}
if (memoryLabel.isDisplay()) {
memoryLabel.setText(AppUtil.getMemoryLoad());
if (LabelLayout.DOUBLE == window.getLabelLayout() && !Objects.isNull(gridLayout)) {
gridLayout.addLayoutComponent("memoryLabel", memoryLabel);
}
window.add(memoryLabel);
}
if (batteryLabel.isDisplay()) {
batteryLabel.setText(AppUtil.getBatteryPercent());
if (LabelLayout.DOUBLE == window.getLabelLayout() && !Objects.isNull(gridLayout)) {
gridLayout.addLayoutComponent("batteryLabel", batteryLabel);
}
window.add(batteryLabel);
}
if (timeLabel.isDisplay()) {
timeLabel.setText(AppUtil.getTime());
if (LabelLayout.DOUBLE == window.getLabelLayout() && !Objects.isNull(gridLayout)) {
gridLayout.addLayoutComponent("timeLabel", timeLabel);
}
window.add(timeLabel);
}
}
private int getDisplayLabelCount() {
int count = 0;
if (cpuLabel.isDisplay()) {
count++;
}
if (memoryLabel.isDisplay()) {
count++;
}
if (batteryLabel.isDisplay()) {
count++;
}
if (timeLabel.isDisplay()) {
count++;
}
return count;
}
private GridLayout updateWindowLabelLayout(int count) {
GridLayout gridLayout = null;
if (LabelLayout.SINGLE == window.getLabelLayout()) {
// 单列布局
window.setSize(window.getWidth(), 20 * count);
} else if (LabelLayout.DOUBLE == window.getLabelLayout()) {
// 双列布局
switch (count) {
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);
}
}
AppUtil.initWindowLocation(window);
return gridLayout;
}
private void windowRemoveAll() {
window.remove(cpuLabel);
window.remove(memoryLabel);
window.remove(batteryLabel);
window.remove(timeLabel);
}
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) {
window.setLabelLayout(LabelLayout.SINGLE);
window.setSize(85, 80);
window.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 1));
reloadWindow();
AppUtil.initWindowLocation(window);
refreshWindow();
}
});
JMenuItem doubleJMenuItem = new JMenuItem("双列布局");
doubleJMenuItem.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
window.setLabelLayout(LabelLayout.DOUBLE);
window.setSize(150, 40);
window.setLayout(new GridLayout(2, 2));
reloadWindow();
AppUtil.initWindowLocation(window);
refreshWindow();
}
});
doubleJMenuItem.setFont(font);
layoutJMenu.add(singleJMenuItem);
layoutJMenu.add(doubleJMenuItem);
jPopupMenu.add(layoutJMenu);
}
private void setRefreshJMenu() {
JMenuItem refreshJMenuItem = new JMenuItem("刷新");
refreshJMenuItem.setFont(font);
refreshJMenuItem.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
refreshWindow();
}
});
jPopupMenu.add(refreshJMenuItem);
}
private void refreshWindow() {
window.setVisible(false);
window.setVisible(true);
}
private void setMovableJMenu() {
JMenuItem movableJMenuItem = new JMenuItem("移动");
movableJMenuItem.setFont(font);
movableJMenuItem.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
windowMovable.setValue(!windowMovable.getValue());
if (windowMovable.isTrue()) {
movableJMenuItem.setText("固定");
} else {
movableJMenuItem.setText("移动");
}
}
});
jPopupMenu.add(movableJMenuItem);
}
private void setJFrame() {
this.jFrame = new JFrame();
// 设置无边框
jFrame.setUndecorated(true);
// 隐藏任务栏图标
jFrame.setType(JFrame.Type.UTILITY);
// 设置窗口置顶
jFrame.setAlwaysOnTop(true);
// 设置背景颜色
jFrame.setBackground(new Color(255, 255, 255, 255));
// 设置窗体大小
jFrame.setSize(WIDTH, HEIGHT);
// 设置布局
jFrame.setLayout(new GridLayout(5, 1));
}
public void display(MouseEvent mouseEvent) {
hiddenFrameIfShowing();
hiddenJPopupMenuIfShowing();
jFrame.setLocation(mouseEvent.getX() - WIDTH, mouseEvent.getY() - HEIGHT);
jFrame.setVisible(true);
jPopupMenu.show(jFrame, 0, 0);
// System.out.println("Width=" + jPopupMenu.getWidth() + "Height=" +
// jPopupMenu.getHeight());
}
}
Dll.java
package cxzgwing.dll;
import com.sun.jna.Library;
import com.sun.jna.Native;
public interface Dll extends Library {
Dll dll = Native.load("BatteryMonitor", Dll.class);
int BatteryPercent();
}
AppUtil.java
package cxzgwing.utils;
import java.awt.*;
import java.lang.management.ManagementFactory;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import com.sun.management.OperatingSystemMXBean;
import cxzgwing.Window;
import cxzgwing.dll.Dll;
public class AppUtil {
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) {
e.printStackTrace();
}
return "B: " + value + "%";
}
public static void initWindowLocation(Window window) {
// 获得窗体宽
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());
window.setWindowMaxX(screenWidth - windowWidth);
window.setWindowMaxY(screenHeight - windowHeight - screenInsets.bottom);
// 设置窗口相对于指定组件的位置:置于屏幕的中央
// frame.setLocationRelativeTo(null);
// 设置窗体默认在屏幕右下角
window.setLocation(window.getWindowMaxX(), window.getWindowMaxY());
}
}
BatteryLabel.java
package cxzgwing.label.impl;
import cxzgwing.label.LabelAdaptor;
public class BatteryLabel extends LabelAdaptor {
private boolean display;
public BatteryLabel(String text) {
this.setText(text);
this.display = true;
}
@Override
public boolean isDisplay() {
return display;
}
@Override
public void setDisplay(boolean display) {
this.display = display;
}
}
C++创建dll
BatteryMonitor.h
#ifdef BATTERYMONITOR_EXPORTS
#define BATTERYMONITOR_API __declspec(dllexport)
#else
#define BATTERYMONITOR_API __declspec(dllimport)
#endif
extern "C" BATTERYMONITOR_API int BatteryPercent();
BatteryMonitor.cpp
#include "pch.h"
#include <iostream>
#define BATTERYMONITOR_EXPORTS
#include "BatteryMonitor.h"
#include <Windows.h>
using namespace std;
BATTERYMONITOR_API int BatteryPercent(){
SYSTEM_POWER_STATUS sysPowerStatus;
GetSystemPowerStatus(&sysPowerStatus);
return (int)sysPowerStatus.BatteryLifePercent;
}
依赖
<?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.0.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>
</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
Gitee
system-monitoring: Java Swing applet, real-time monitoring system CPU usage and memory usage.
参考链接
[1] 晨曦之光Wing.Java简易系统监视器. 2021-06-13 18:08:36
https://blog.youkuaiyun.com/qq_36533690/article/details/117881862
[2] xietansheng.Java Swing 图形界面开发(目录).2017-05-30 23:50:42
https://xiets.blog.youkuaiyun.com/article/details/72814492
[3] lucky__cc.【Swing】Java Swing JPopupMenu:弹出式菜单. 2019-08-06 22:03:34
https://blog.youkuaiyun.com/qq1437722579/article/details/98663286
[4] 艾斯曼.一个找了很久的API函数---GetSystemPowerStatus.2013-01-23 21:47:51
https://blog.youkuaiyun.com/wangqiulin123456/article/details/8535809
[5] 晨曦之光Wing.Java调用dll文件.2021-11-10 11:06:51
https://blog.youkuaiyun.com/qq_36533690/article/details/121239139
后记
此次是在之前的基础之上修改的,由两个问题引发,一是笔记本电池之前鼓包,买了新电池,想要实时查看电量。二是全屏看视频时有时候想看时间(全屏看视频时,这个窗体会一直显示)。所以就加上了显示电量和时间两个指标。
经过一番查询,发现C++可以读取电池数据,C++创建动态链接库dll文件,再通过Java使用jna调用dll文件。于是就自己干!写C++,做dll!(我发现用C++创建动态链接库dll文件会上瘾,没办法,C++太强大了)
进一步考虑到有些小伙伴可能用台式机,不需要电量信息,甚至不需要CPU使用率或者内存使用率或者时间,干脆就做成动态的算了,于是托盘菜单新增了“显示”按钮,可勾选显示的内容。
考虑到如果只显示一个参数或两个参数,原布局就很丑了,干脆加一个调整布局按钮,于是托盘菜单新增了“布局”按钮,可修改布局。
后面发现,布局和显示混合使用,情况多样,有的情况又很丑了,索性做成了动态布局,窗体根据显示的参数个数自动适配布局。
进一步开发,后来发现已采用的菜单栏的创建方案二使用JPopupMenu会导致多级菜单栏有问题,jPopupMenu.show(Component invoker, int x, int y)需要有Component(不加的话多级菜单的子菜单就弹不出来),但是系统托盘这玩意儿SystemTray它不是Component……所以想了个方法,直接新建一个JFrame,用它来和JPopupMenu绑定,JFrame和JPopupMenu大小一致,且显示和隐藏的状态一致就哦了,然后就大改了……嗯,面目全非、惨不忍睹。
然后发现新方法在弹出系统托盘菜单后,鼠标点击非菜单区域,菜单会自动消失(之前是不会的,所以用了jnativehook做全局鼠标监听,配合鼠标的位置判断,达到该效果),所以就不需要用jnativehook了。
最后为了方便和那什么,封装了Label,用了线程池。