Java简易系统监视器system-monitoring

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

目录

效果图

功能说明

项目与工具

项目说明

目录结构

核心代码

Window.java

Dll.java

AppUtil.java

BatteryLabel.java

C++创建dll

BatteryMonitor.h

BatteryMonitor.cpp

依赖

Github

Gitee

参考链接

后记


效果图

功能说明

  1. Java简易系统监视器system-monitoring:实时显示CPU使用率、内存使用率、笔记本电脑电池剩余电量、时间(时、分、秒)。CPU使用率、内存使用率和时间每秒更新一次,笔记本电脑电池剩余电量每15秒更新一次。
  2. 创建系统托盘,设置系统托盘菜单,窗体置顶显示。
  3. 系统托盘按钮:
    1. 移动(或固定):点击后可移动或固定窗体。
    2. 刷新:点击可刷新窗体,当窗体显示异常时可使用。
    3. 布局:可更改窗体布局,可选“单列布局”、“双列布局”。(效果图为双列布局)
    4. 显示:可选择需要显示的参数,可勾选“CPU”、“内存”、“电量”、“时间”。
    5. 退出程序:点击可退出程序。
  4. 窗体不可移动至屏幕外。
  5. 窗体大小可根据显示的参数个数自动适配。
  6. 点击系统托盘后,弹出多级菜单,当鼠标点击非菜单区域,弹出的多级菜单会自动消失。(基于JFrame+JPopupMenu实现)

项目与工具

Maven、Java 8、Swing、maven-assembly-plugin(jar-with-dependencies)、jna、dll

项目说明

  1. 使用jna调用C++生成的动态链接库dll文件监控电池剩余电量。
  2. 生成的system-monitoring-2.0.0-jar-with-dependencies.jar需与resources中的images文件夹和BatteryMonitor.dll文件同级。(与代码中读取相关文件路径的写法有关)

目录结构

核心代码

由于代码较多,此处就不全部贴出来了,需要完整代码的小伙伴请移步GitHubGitee

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;
    }

}
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

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] 晨曦之光Wing.Java简易系统监视器. 2021-06-13 18:08:36
https://blog.csdn.net/qq_36533690/article/details/117881862


[2] xietansheng.Java Swing 图形界面开发(目录).2017-05-30 23:50:42
https://xiets.blog.csdn.net/article/details/72814492


[3] lucky__cc.【Swing】Java Swing JPopupMenu:弹出式菜单. 2019-08-06 22:03:34
https://blog.csdn.net/qq1437722579/article/details/98663286


[4] 艾斯曼.一个找了很久的API函数---GetSystemPowerStatus.2013-01-23 21:47:51
https://blog.csdn.net/wangqiulin123456/article/details/8535809


[5] 晨曦之光Wing.Java调用dll文件.2021-11-10 11:06:51
https://blog.csdn.net/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,用了线程池。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值