Java simple system monitoring: real-time display of CPU utilization, memory utilization, remaining power of laptop battery and time (hour, minute and second). Create the system tray, set the system tray menu, and display the form on the top. Read battery data by jna calling dll file.
catalogue
design sketch
Function description
- Java simple system monitoring: real-time display of CPU utilization, memory utilization, remaining power of laptop battery and time (hour, minute and second). CPU usage, memory usage and time are updated every second, and the remaining battery power of laptop is updated every 15 seconds.
- Create the system tray, set the system tray menu, and display the form on the top.
- System tray button:
- Move (or fix): Click to move or fix the form.
- Refresh: Click to refresh the form. It can be used when the form displays exceptions.
- Layout: you can change the form layout, including single column layout and double column layout. (the effect drawing is a double column layout)
- Display: you can select the parameters to be displayed, and check "CPU", "memory", "power" and "time".
- Exit program: Click to exit the program.
- The form cannot be moved off screen.
- The size of the form can be automatically adapted according to the number of parameters displayed.
- After clicking the system tray, a multi-level menu will pop up. When the mouse clicks the non menu area, the pop-up multi-level menu will disappear automatically. (based on JFrame+JPopupMenu)
Projects and tools
Maven,Java 8,Swing,maven-assembly-plugin(jar-with-dependencies),jna,dll
Project description
- The dynamic link library dll file generated by jna calling C + + is used to monitor the remaining battery power.
- Generated system-monitoring-2.0.0-jar-with-dependencies Jar needs to be associated with the images folder and batterymonitor. Jar in resources DLL file sibling. (related to the writing method of reading the relevant file path in the code)
directory structure
Core code
Due to the large number of codes, not all of them will be posted here. Please move on if you need a complete code GitHub or 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-single column layout, 2-double column layout private int labelLayout; // Maximum abscissa of form position private int windowMaxX; // Maximum ordinate of form position private int windowMaxY; public Window() throws Exception { // Initializes whether the form is movable windowMovable = new WindowMovable(false); font = new Font("Blackbody", Font.PLAIN, 16); labelLayout = LabelLayout.DOUBLE; // Set display label margins emptyBorder = new EmptyBorder(0, 5, 0, 0); // Set layout gridLayout = new GridLayout(2, 2); // Initialize form initWindow(); // Set CPU usage Display tab initCpuJLabel(); // Memory usage Display tab initMemJLabel(); // Battery power percentage display label initBatteryJLabel(); // Time display label initTimeJLabel(); // Initialize tray menu initMenu(); // Set whether the form can be moved setWindowDragListener(); // Add form status listener to keep the form displayed all the time setWindowAlwaysShow(); // Add system tray setSystemTray(); // display this.setVisible(true); // monitor monitoring(); } private void initMenu() { menu = new Menu(this, windowMovable, cpuLabel, memoryLabel, batteryLabel, timeLabel); } /** * Initialize the form to display CPU utilization and Mem utilization */ private void initWindow() { // Hide taskbar icon this.setType(JFrame.Type.UTILITY); // Set window top this.setAlwaysOnTop(true); // Set borderless this.setUndecorated(true); // Set background color this.setBackground(new Color(0, 0, 0, 80)); // Set form size this.setSize(150, 40); // Set layout this.setLayout(gridLayout); AppUtil.initWindowLocation(this); } private void setWindowDragListener() { // Set mouse monitoring. You can move the window position with the mouse // The first button (move / fix) in the system tray menu controls whether the form can be moved FrameDragListener frameDragListener = new FrameDragListener(this, windowMovable); this.addMouseListener(frameDragListener); this.addMouseMotionListener(frameDragListener); } private void initTimeJLabel() { // Time display label 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() { // Battery power percentage display label 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() { // Memory usage Display tab 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 usage Display tab cpuLabel = new CpuLabel(AppUtil.getSystemCpuLoad()); cpuLabel.setFont(font); cpuLabel.setForeground(Color.WHITE); cpuLabel.setBorder(emptyBorder); gridLayout.addLayoutComponent("cpuLabel", cpuLabel); this.add(cpuLabel); } /** * monitor */ private void monitoring() { ThreadUtil.addTask(new CpuMemoryTimeMonitorTask(cpuLabel, memoryLabel, timeLabel)); ThreadUtil.addTask(new BatteryMonitorTask(batteryLabel)); ThreadUtil.addTask(new GCTask()); } /** * Add system tray */ private void setSystemTray() throws Exception { try { if (SystemTray.isSupported()) { // Get the system tray of the current platform SystemTray tray = SystemTray.getSystemTray(); // Load a picture for the display of tray icons Image image = Toolkit.getDefaultToolkit() .getImage(Clock.class.getResource("/images/system-monitoring-icon.png")); // Create pop-up menu scheme 3 when clicking the icon: JFrame + JPopupMenu TrayIcon trayIcon = new TrayIcon(image, "System Monitoring"); trayIcon.addMouseListener(new TrayIconMouseListener(menu)); // Tray icon adaptive size trayIcon.setImageAutoSize(true); // Add tray icon to system tray tray.add(trayIcon); } else { throw new Exception("The current system does not support system trays"); } } catch (Exception e) { e.printStackTrace(); throw e; } } /** * Add form status listener to keep the form displayed all the time */ 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("Song typeface", 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("Exit program"); 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("display"); 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("Memory"); memoryJCheckBox.setFont(font); memoryJCheckBox.setSelected(true); memoryJCheckBox.addMouseListener(new MouseAdapter() { @Override public void mouseReleased(MouseEvent e) { stateChange(memoryLabel, memoryJCheckBox.isSelected()); } }); JCheckBox batteryJCheckBox = new JCheckBox("Electric quantity"); batteryJCheckBox.setFont(font); batteryJCheckBox.setSelected(true); batteryJCheckBox.addMouseListener(new MouseAdapter() { @Override public void mouseReleased(MouseEvent e) { stateChange(batteryLabel, batteryJCheckBox.isSelected()); } }); JCheckBox timeJCheckBox = new JCheckBox("time"); 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) { // Press the mouse in the check box and release the mouse after removing the check box area. At this time, the check box state remains unchanged and no operation is required 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) { // Since the relevant data is not read when the label is not displayed, the data needs to be updated when it is displayed again 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()) { // Single column layout window.setSize(window.getWidth(), 20 * count); } else if (LabelLayout.DOUBLE == window.getLabelLayout()) { // Double column layout 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("layout"); layoutJMenu.setFont(font); JMenuItem singleJMenuItem = new JMenuItem("Single column layout"); 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("Double column layout"); 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("Refresh"); 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("move"); movableJMenuItem.setFont(font); movableJMenuItem.addMouseListener(new MouseAdapter() { @Override public void mouseReleased(MouseEvent e) { windowMovable.setValue(!windowMovable.getValue()); if (windowMovable.isTrue()) { movableJMenuItem.setText("fixed"); } else { movableJMenuItem.setText("move"); } } }); jPopupMenu.add(movableJMenuItem); } private void setJFrame() { this.jFrame = new JFrame(); // Set borderless jFrame.setUndecorated(true); // Hide taskbar icon jFrame.setType(JFrame.Type.UTILITY); // Set window top jFrame.setAlwaysOnTop(true); // Set background color jFrame.setBackground(new Color(255, 255, 255, 255)); // Set form size jFrame.setSize(WIDTH, HEIGHT); // Set layout 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) { // Get form width int windowWidth = window.getWidth(); // Get form height int windowHeight = window.getHeight(); // Define Toolkit Toolkit kit = Toolkit.getDefaultToolkit(); // Gets the size of the screen Dimension screenSize = kit.getScreenSize(); // Gets the width of the screen int screenWidth = screenSize.width; // Gets the height of the screen int screenHeight = screenSize.height; // Get taskbar Insets screenInsets = kit.getScreenInsets(window.getGraphicsConfiguration()); window.setWindowMaxX(screenWidth - windowWidth); window.setWindowMaxY(screenHeight - windowHeight - screenInsets.bottom); // Sets the position of the window relative to the specified component: placed in the center of the screen // frame.setLocationRelativeTo(null); // Set the default form in the lower right corner of the screen 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 + + create 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; }
rely on
<?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.
Reference link
[1] Morning light wing Java simple system monitor 2021-06-13 18:08:36
https://blog.csdn.net/qq_36533690/article/details/117881862
[2] xietansheng.Java Swing graphical interface development (directory). 2017-05-30 23:50:42
https://xiets.blog.csdn.net/article/details/72814492
[3] lucky__cc. [Swing] Java Swing JPopupMenu: pop up menu 2019-08-06 22:03:34
https://blog.csdn.net/qq1437722579/article/details/98663286
[4] Eisman An API function that has been found for a long time -- getsystempowerstatus 2013-01-23 21:47:51
https://blog.csdn.net/wangqiulin123456/article/details/8535809
[5] Morning light wing Java call dll file. 2021-11-10 11:06:51
https://blog.csdn.net/qq_36533690/article/details/121239139
Postscript
This time, it was modified on the basis of the previous. It was caused by two problems. One was that the laptop battery was bulging before and bought a new battery to check the power in real time. Second, sometimes I want to see the time when watching the video in full screen (this window will always be displayed when watching the video in full screen). Therefore, two indicators of display power and time are added.
After some inquiry, it is found that C + + can read battery data, C + + creates dynamic link library dll file, and then calls dll file using jna through Java. So do it yourself! Write c + +, do dll! (I find it addictive to use C + + to create dll files of dynamic link library. I can't help it. C + + is too powerful)
Further, considering that some small partners may use desktop computers and do not need power information, or even CPU utilization or memory utilization or time, they simply make it dynamic, so the "display" button is added to the tray menu to check the displayed content.
Considering that if only one or two parameters are displayed, the original layout will be ugly. Simply add an adjust layout button, so the "layout" button is added in the tray menu to modify the layout.
Later, it was found that the mixed use of layout and display has a variety of situations, and some situations are ugly. It was simply made into a dynamic layout, and the form automatically adapts to the layout according to the number of displayed parameters.
After further development, it was found that the adopted menu bar creation scheme II. Using JPopupMenu will lead to problems with multi-level menu bars, JPopupMenu Show (Component invoker, int x, int y) requires a Component (if it is not added, the submenu of the multi-level menu will not pop up), but the system tray is SystemTray. It is not a Component... So I think of a way to directly create a JFrame and bind it with JPopupMenu. JFrame and JPopupMenu are the same size, and the displayed and hidden states are the same, Then it changed... Well, it was beyond recognition and terrible.
Then it is found that after the system tray menu pops up, click the non menu area with the mouse, and the menu will disappear automatically (it was not before, so jnativehook is used for global mouse monitoring, and the effect is achieved by matching the mouse position judgment). Therefore, jnativehook is not needed.
Finally, in order to facilitate and what, the Label is encapsulated and the thread pool is used.