目錄
前言
在我學習了JavaSE 和 基本的數據結構以及多線程的知識後,我想着做些什麼東西來鞏固我所寫的知識。於是我就做了實際中我們用電腦可以使用到的功能,實時統計CPU的佔有率並繪製曲線,統計磁盤某個文件目錄下子目錄、子文件所佔空間的大小 。
項目所用技術與平臺
所用技術:JavaSE/javafx
平臺與環境:Windows 10/jdk1.8/idea
項目功能
顯示 CPU 佔有率
文件目錄掃描
項目模塊分析
主要分爲UI模塊和邏輯模塊。
UI部分主程序用來加載fxml文件,Controller 主要功能是把UI和邏輯部分關聯起來,再就是進行兩個Tab頁的設計。
邏輯部分主要實現兩個功能:1. CPU佔用率的獲取 2. 磁盤目錄的掃描
項目細節實現
UI模塊
1. 主函數
package com.bq.gui;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
/*
主程序:繼承Application類 重寫start()方法
*/
public class FileAndOSMonitorApp extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
//Stage:舞臺 Scene:場景
//1. 加載.fxml文件
FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().
getResource("FOMonitor_tab.fxml"));
//2. 真正的加載
Parent root = loader.load();
//加載磁盤空間統計 把統計頁面加載到主舞臺
FileAndOSMonitorController controller = loader.getController();
controller.setPrimaryStage(primaryStage);
//3. 創建Scene對象 即場景
Scene scene = new Scene(root, 800, 600);
//4. 給stage設置標題
primaryStage.setTitle("FileAndOSMonitor");
//5. 將scene添加到stage
primaryStage.setScene(scene);
//關閉時停止程序
primaryStage.setOnCloseRequest(event -> controller.shutdown());
//6. 展示
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
對主函數進行了一些解釋,其實主函數更多像一個死套路,繼承Application類 重寫start()方法,主要目的是進行資源的加載。
2. 磁盤空間掃描Tab頁設計
要用自己設計的 UI 替換工程自動生成的 .fxml 文件。 UI 的主題框架是通過 fxml 來描述。UI 交互比較簡單,只有兩個 tab 頁。fxml 中所有元素名稱都是 JavaFX 中的類名或者是類的屬性名。元素的屬性是 JavaFX中類的屬性。 這個 UI 主框架包含兩個 tab 頁,用到的控件是<TabPane> 和 <Tab> 。 <TabPane> 代表 tab 頁所在的容器面板, 代表一個個的 tab 頁。
CPU 佔有率 = CPU 執行程序時間 / 統計週期時間。CPU 佔有率 Tab 頁主要是通過 <LineChart> 控件繪製曲線圖,x 軸 和 y 軸都用 <NumberAxis> 控 件。通過 <Tab> 控件的 onSelectionChanged 屬性設置監聽事件的方法:handleCPUSelectionChanged。
描述一下,磁盤空間掃描Tab頁所用的重要控件:
1. <VBox></VBox>:爲垂直佈局,佈局面板爲將多個節點排列在一列中提供了一個簡單的方法。
2. <HBox></HBox>:爲水平佈局,佈局面板爲將多個節點排列在一行中提供了一個簡單的方法。
3. <TabPane> </TabPane>:頁籤面板,是一種標籤頁控件。
4. <Tab></Tab>:每個Tab頁就可以響應一個頁面,可以進行頁面間的切換。
5. <LineChart></LineChart>:網格控件,用來顯示實時顯示cpu佔有率。
6. <GridPane></GridPane>:單元格控件,用來顯示系統資源的獲取情況。
7. <Text></Text>:可編輯的文本頁。
8. <Lable></Lable>:標籤頁。
總體的佈局可以由下圖表示:
3. 文件目錄統計Tab頁設計
磁盤掃描 Tab 頁主要是用到了 <TreeTableView> 控件,繪製一個樹形表格。另外設計了一個<Button> 控件來選擇文件目錄,通 <Button> 控件的 onAction 屬性設置監聽事件的方法: handleSelectFile。
主要有兩個重要的控件:
1. <Button></Button>:按鈕組件,會有具體的響應方法。
2.<TreeTableView></TreeTableView>:樹表組件,既有樹的特性,又有表的特性。用於文件目錄的樹形結構的查看。
總體的佈局可以由下圖表示:
4. Controller 模塊
Controller 主要是用於處理 UI 事件,需要將此類添加到 .fxml 文件中,我用到的頂級容器是 <VBox> ,通過 fx:controller 屬性設置 Controller 類的包路徑,方法如下:
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="com.bq.gui.FileAndOSMonitorController">
</VBox>
在 Controller 中,我們需要處理兩個事件:CPU 佔有率和目錄結構統計,詳情見github,大致流程如下:
// 磁盤目錄掃描事件處理方法
public void handleSelectFile(ActionEvent actionEvent) {
// 1. 打開文件選擇對話框
// 2. 開啓磁盤目錄掃描線程
// 3. 渲染TreeTableView
}
// CPU 佔有率事件處理方法
public void handleCPUSelectionChanged(Event event) {
// 1. 創建一個定時器,每隔一秒獲取一次 CPU 資源繪製曲線圖
// 2. 繪製 LineChart
}
邏輯模塊
1. 系統資源獲取模塊
系統資源獲取採用的是 OperatingSystemMXBean,這是一個 JMX 接口,用於獲取運行 JVM 的系統的 資源信息,比如,CPU 佔有率,OS 版本,內存大小等等。我們用的是 com.sun.management.OperatingSystemMXBean 類。
繪製 CPU 佔有率曲線的核心思想:
1. 每隔一秒對 CPU 佔有率進行一次採樣,作爲數軸的 y 座標
2. 一共保存 60 秒,即 1 分鐘的樣本點,時間作爲 x 座標。
3. 用一個數組保存座標 (x,y),每一次採樣,需要把之前採樣的座標點的 x 座標減 1,這樣繪製的時候就會產生移動的效果。
核心代碼如下:
//移動數據
private static final int DATA_LENGTH = 60;
private static XYPair[] xyPairs = new XYPair[DATA_LENGTH];
private static int firstIndex = DATA_LENGTH;
private static void moveCPUData(double cpuPercetage){
int movIdx = -1; //移動的座標
if (firstIndex == 0){
movIdx = firstIndex + 1;
}else
{
movIdx = firstIndex; firstIndex--;
}
for (; movIdx < xyPairs.length; ++movIdx){
xyPairs[movIdx-1].setX(xyPairs[movIdx].getX()-1);
xyPairs[movIdx-1].setY(xyPairs[movIdx].getY());
}
movIdx--;
xyPairs[movIdx] = new XYPair(movIdx, cpuPercetage);
}
2. 文件目錄掃描模塊
文件目錄掃描核心思想是:用遞歸的方式遍歷文件目錄結構,統計某個目錄下面所有子目錄佔用總的磁盤空間大小,然後再做一個彙總。
代碼片段:
public static void scannerDirectory(FileTreeNode node) {
//獲取當前目錄或文件列表
File[] files = node.getFile().listFiles();
if (files == null) {
return;
}
//遍歷子目錄或者文件
for (File file : files) {
FileTreeNode child = new FileTreeNode();
child.setFile(file);
child.setFileName(file.getName());
if (file.isDirectory()) {
//如果是目錄繼續統計
scannerDirectory(child);
} else {
//如果是普通文件 記錄文件大小
child.setTotalLength(file.length());
}
node.setTotalLength(node.getTotalLength() + child.getTotalLength());
node.addChildNode(child);
}
}
項目演示
項目總結
這個項目實現了完整的功能,鞏固了我對前面知識的學習。在項目中,我也遇到了一些問題:比如gui程序渲染數據必須在主線程中執行,樹表控件的轉化等等,也都進行了克服。當然還有很多的不足,需要繼續完善。
- 項目優點:引入了 JavaFX 技術,通過圖形化 界面展示 CPU 佔有率和磁盤空間統計,顯得更直觀。
- 項目缺點:項目的所實現的功能相對簡單,UI 不夠美觀。
- 項目擴展:還可以把項目寫的更完善比如: 增加關於內存使用情況的統計,增加關於網絡上下行帶寬的統計,美化UI,這是我後面要做的工作。
附:github鏈接 。