diff --git a/src/main/java/com/luoboduner/moo/info/ui/Init.java b/src/main/java/com/luoboduner/moo/info/ui/Init.java
index 1c55b04..1029178 100644
--- a/src/main/java/com/luoboduner/moo/info/ui/Init.java
+++ b/src/main/java/com/luoboduner/moo/info/ui/Init.java
@@ -205,6 +205,7 @@ public class Init {
ThreadUtil.execute(NetworkForm::init);
ThreadUtil.execute(UsbForm::init);
ThreadUtil.execute(VariablesForm::init);
+ ThreadUtil.execute(ProcessesForm::init);
// Check the new version
if (App.config.isAutoCheckUpdate()) {
diff --git a/src/main/java/com/luoboduner/moo/info/ui/UiConsts.java b/src/main/java/com/luoboduner/moo/info/ui/UiConsts.java
index e4e33d0..83fe712 100644
--- a/src/main/java/com/luoboduner/moo/info/ui/UiConsts.java
+++ b/src/main/java/com/luoboduner/moo/info/ui/UiConsts.java
@@ -74,5 +74,10 @@ public class UiConsts {
*/
public static final String CHECK_VERSION_URL = "https://gitee.com/zhoubochina/MooInfo/raw/master/src/main/resources/version_summary.json";
+ public static final int REFRESH_FAST = 1000;
+ public static final int REFRESH_SLOW = 5000;
+
+ public static final int REFRESH_SLOWER = 15_000;
+
}
diff --git a/src/main/java/com/luoboduner/moo/info/ui/form/MainWindow.form b/src/main/java/com/luoboduner/moo/info/ui/form/MainWindow.form
index 6ef2c95..7a6775c 100644
--- a/src/main/java/com/luoboduner/moo/info/ui/form/MainWindow.form
+++ b/src/main/java/com/luoboduner/moo/info/ui/form/MainWindow.form
@@ -82,7 +82,7 @@
-
+
diff --git a/src/main/java/com/luoboduner/moo/info/ui/form/MainWindow.java b/src/main/java/com/luoboduner/moo/info/ui/form/MainWindow.java
index 8dcfd90..fd3f5fc 100644
--- a/src/main/java/com/luoboduner/moo/info/ui/form/MainWindow.java
+++ b/src/main/java/com/luoboduner/moo/info/ui/form/MainWindow.java
@@ -22,6 +22,7 @@ public class MainWindow {
private JPanel detailPanel;
private JPanel usbPanel;
private JPanel VariablesPanel;
+ private JPanel processesPanel;
private static MainWindow mainWindow;
@@ -44,6 +45,7 @@ public class MainWindow {
mainWindow.getNetworkPanel().add(NetworkForm.getInstance().getMainPanel(), gridConstraints);
mainWindow.getUsbPanel().add(UsbForm.getInstance().getMainPanel(), gridConstraints);
mainWindow.getVariablesPanel().add(VariablesForm.getInstance().getMainPanel(), gridConstraints);
+ mainWindow.getProcessesPanel().add(ProcessesForm.getInstance().getMainPanel(), gridConstraints);
mainWindow.getMainPanel().updateUI();
}
@@ -88,9 +90,9 @@ public class MainWindow {
VariablesPanel = new JPanel();
VariablesPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
tabbedPane.addTab("Variables", VariablesPanel);
- final JPanel panel4 = new JPanel();
- panel4.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
- tabbedPane.addTab("Processes", panel4);
+ processesPanel = new JPanel();
+ processesPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
+ tabbedPane.addTab("Processes", processesPanel);
usbPanel = new JPanel();
usbPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
tabbedPane.addTab("USB Devices", usbPanel);
diff --git a/src/main/java/com/luoboduner/moo/info/ui/form/ProcessesForm.form b/src/main/java/com/luoboduner/moo/info/ui/form/ProcessesForm.form
new file mode 100644
index 0000000..acd33de
--- /dev/null
+++ b/src/main/java/com/luoboduner/moo/info/ui/form/ProcessesForm.form
@@ -0,0 +1,26 @@
+
+
diff --git a/src/main/java/com/luoboduner/moo/info/ui/form/ProcessesForm.java b/src/main/java/com/luoboduner/moo/info/ui/form/ProcessesForm.java
new file mode 100644
index 0000000..cd6182e
--- /dev/null
+++ b/src/main/java/com/luoboduner/moo/info/ui/form/ProcessesForm.java
@@ -0,0 +1,181 @@
+package com.luoboduner.moo.info.ui.form;
+
+import cn.hutool.log.Log;
+import cn.hutool.log.LogFactory;
+import com.intellij.uiDesigner.core.GridConstraints;
+import com.intellij.uiDesigner.core.GridLayoutManager;
+import com.luoboduner.moo.info.App;
+import com.luoboduner.moo.info.ui.UiConsts;
+import lombok.Getter;
+import oshi.PlatformEnum;
+import oshi.SystemInfo;
+import oshi.software.os.OSProcess;
+import oshi.software.os.OperatingSystem;
+import oshi.util.FormatUtil;
+
+import javax.swing.*;
+import javax.swing.table.DefaultTableModel;
+import javax.swing.table.TableColumn;
+import javax.swing.table.TableColumnModel;
+import javax.swing.table.TableModel;
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * NetworkForm
+ *
+ * @author RememBerBer
+ * @since 2021/11/15.
+ */
+@Getter
+public class ProcessesForm {
+ private static final String[] COLUMNS = {"PID", "PPID", "Threads", "% CPU", "Cumulative", "VSZ", "RSS", "% Memory",
+ "Process Name"};
+ private static final double[] COLUMN_WIDTH_PERCENT = {0.07, 0.07, 0.07, 0.07, 0.09, 0.1, 0.1, 0.08, 0.35};
+
+ private transient static Map priorSnapshotMap = new HashMap<>();
+
+ private static final Log logger = LogFactory.get();
+
+ private static ProcessesForm processesForm;
+ private JPanel mainPanel;
+ private JTable processTable;
+
+ public static ProcessesForm getInstance() {
+ if (processesForm == null) {
+ processesForm = new ProcessesForm();
+ }
+ return processesForm;
+ }
+
+ public static void init() {
+ processesForm = getInstance();
+
+ initUi();
+ initInfo();
+ }
+
+ private static void initUi() {
+ }
+
+ private static void initInfo() {
+ OperatingSystem os = App.si.getOperatingSystem();
+ TableModel model = new DefaultTableModel(parseProcesses(os.getProcesses(null, null, 0), App.si), COLUMNS);
+ JTable procTable = getInstance().getProcessTable();
+ procTable.setModel(model);
+ resizeColumns(procTable.getColumnModel());
+
+ Timer timer = new Timer(UiConsts.REFRESH_SLOW, e -> {
+ DefaultTableModel tableModel = (DefaultTableModel) procTable.getModel();
+ Object[][] newData = parseProcesses(os.getProcesses(null, null, 0), App.si);
+ int rowCount = tableModel.getRowCount();
+ for (int row = 0; row < newData.length; row++) {
+ if (row < rowCount) {
+ // Overwrite row
+ for (int col = 0; col < newData[row].length; col++) {
+ tableModel.setValueAt(newData[row][col], row, col);
+ }
+ } else {
+ // Add row
+ tableModel.addRow(newData[row]);
+ }
+ }
+ // Delete any extra rows
+ for (int row = rowCount - 1; row >= newData.length; row--) {
+ tableModel.removeRow(row);
+ }
+ });
+ timer.start();
+ }
+
+ private static Object[][] parseProcesses(List list, SystemInfo si) {
+ long totalMem = si.getHardware().getMemory().getTotal();
+ int cpuCount = si.getHardware().getProcessor().getLogicalProcessorCount();
+ // Build a map with a value for each process to control the sort
+ Map processSortValueMap = new HashMap<>();
+ for (OSProcess p : list) {
+ int pid = p.getProcessID();
+ // Ignore the Idle process on Windows
+ if (pid > 0 || !SystemInfo.getCurrentPlatform().equals(PlatformEnum.WINDOWS)) {
+ // Set up for appropriate sort
+ processSortValueMap.put(p, (double) p.getResidentSetSize());
+ }
+ }
+ // Now sort the list by the values
+ List> procList = new ArrayList<>(processSortValueMap.entrySet());
+ procList.sort(Map.Entry.comparingByValue());
+ // Insert into array in reverse order (lowest sort value last)
+ int i = procList.size();
+ Object[][] procArr = new Object[i][COLUMNS.length];
+ // These are in descending CPU order
+ for (Map.Entry e : procList) {
+ OSProcess p = e.getKey();
+ // Matches order of COLUMNS field
+ i--;
+ int pid = p.getProcessID();
+ procArr[i][0] = pid;
+ procArr[i][1] = p.getParentProcessID();
+ procArr[i][2] = p.getThreadCount();
+ {
+ procArr[i][3] = String.format("%.1f",
+ 100d * p.getProcessCpuLoadBetweenTicks(priorSnapshotMap.get(pid)));
+ procArr[i][4] = String.format("%.1f", 100d * p.getProcessCpuLoadCumulative());
+ }
+ procArr[i][5] = FormatUtil.formatBytes(p.getVirtualSize());
+ procArr[i][6] = FormatUtil.formatBytes(p.getResidentSetSize());
+ procArr[i][7] = String.format("%.1f", 100d * p.getResidentSetSize() / totalMem);
+ procArr[i][8] = p.getName();
+ }
+ // Re-populate snapshot map
+ priorSnapshotMap.clear();
+ for (OSProcess p : list) {
+ priorSnapshotMap.put(p.getProcessID(), p);
+ }
+ return procArr;
+ }
+
+ private static void resizeColumns(TableColumnModel tableColumnModel) {
+ TableColumn column;
+ int tW = tableColumnModel.getTotalColumnWidth();
+ int cantCols = tableColumnModel.getColumnCount();
+ for (int i = 0; i < cantCols; i++) {
+ column = tableColumnModel.getColumn(i);
+ int pWidth = (int) Math.round(COLUMN_WIDTH_PERCENT[i] * tW);
+ column.setPreferredWidth(pWidth);
+ }
+ }
+
+ {
+// GUI initializer generated by IntelliJ IDEA GUI Designer
+// >>> IMPORTANT!! <<<
+// DO NOT EDIT OR ADD ANY CODE HERE!
+ $$$setupUI$$$();
+ }
+
+ /**
+ * Method generated by IntelliJ IDEA GUI Designer
+ * >>> IMPORTANT!! <<<
+ * DO NOT edit this method OR call it in your code!
+ *
+ * @noinspection ALL
+ */
+ private void $$$setupUI$$$() {
+ mainPanel = new JPanel();
+ mainPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
+ final JScrollPane scrollPane1 = new JScrollPane();
+ mainPanel.add(scrollPane1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
+ processTable = new JTable();
+ scrollPane1.setViewportView(processTable);
+ }
+
+ /**
+ * @noinspection ALL
+ */
+ public JComponent $$$getRootComponent$$$() {
+ return mainPanel;
+ }
+
+}