前言
上一篇文章介紹了工具的數(shù)據(jù)采集部分,這段時間對工具頁面進行了優(yōu)化:
- 增加清屏功能
- 增加圖表顯示
新版本V1.1.0界面如下所示:

工具介紹
使用方法介紹
使用方法上一篇文章,已經(jīng)大致介紹過了,主要步驟如下:
(電腦環(huán)境配置什么的就不在贅述了)
- 連接手機,點擊檢查設備,正常獲取返回設備SN號,獲取失敗,顯示‘No device found’
- 打開待測應用,點擊獲取,獲取應用包名和activity
- 下拉選擇更新時間
- 開始測試,結(jié)束
- 點擊圖表,顯示圖表(這邊暫時未做到實時顯示圖表,后續(xù)再優(yōu)化)
主界面介紹
基于QT Designer工具,添加需要的pushbutton、textedit等控件,這個上一篇文章已經(jīng)介紹過了,QT Designer的簡單使用,就不再多說了。
這篇文章就重點說一下核心代碼部分和遇到的問題及解決方法吧。
過程中主要遇到了兩個問題:
1.數(shù)據(jù)采集過程中,需要在保留原有數(shù)據(jù)的基礎上,不斷添加新數(shù)據(jù)
2.圖表的展示
流量的統(tǒng)計
數(shù)據(jù)采集部分,主要代碼如下:
采用
adb shell cat /proc/net/xt_qtaguid/stats | findstr uid
命令獲取到的流量是一個total值,而我們需要統(tǒng)計的是一段時間內(nèi)的值,所以這邊采用兩個值相減的方法,即根據(jù)選擇的更新時間,后一個減去前一個的結(jié)果,得到這段時間內(nèi)的統(tǒng)計值
#獲取流量
receive = []
sendflow = []
all = []
def flow():
cmd = 'adb -s '+ get_devices() +' shell cat /proc/net/xt_qtaguid/stats | findstr '+ uid()
print (cmd)
flow_info = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.readlines()
down = 0
up = 0
if len(flow_info)>= 1:
for flow in flow_info:
down =down + int(flow.split()[5])
up = up+ int(flow.split()[7])
receive.append(down)
sendflow.append(up)
print (receive,sendflow)
return (receive,sendflow)
def getflow():
(receive,sendflow) = flow()
recev = []
send = []
allflow = []
print(len(receive))
for i in range(len(receive)-1):
recev.append((int(receive[i+1]) - int(receive[i]))//1024)
send.append((int(sendflow[i+1]) - int(sendflow[i]))//1024)
allflow.append(recev[i]+send[i])
print(recev,send,allflow)
return recev,send,allflow
其他的相對簡單,直接把獲取到的值,最后一個append到textedit中即可以了
QTimer的使用
加入QTimer主要是為了解決,在寫數(shù)據(jù)的過程中,不斷往原有數(shù)據(jù)上append新采集到數(shù)據(jù)的問題,同時不至于是應用無響應。
初始化一個定時器,把定時器的timeout信號和slotadd()槽函數(shù)連接。
self.timer = QTimer(self)
self.timer.timeout.connect(self.slotadd)
slotadd()往五個textedit中寫數(shù)據(jù)
由于返回的數(shù)據(jù)是一個列表,所以每次只需要取最新的即最后一個數(shù)據(jù)即可。
def slotadd(self):
'''
往mem、cpu、flow寫數(shù)據(jù)
:return:
'''
memlist = adb.mem()
mem = 'mem占用:'+ str(memlist[-1])
cpulist = adb.cpu()
cpu = 'cpu占用:'+ str(cpulist[-1])
self.ui.mem.append(mem)
self.ui.cpu.append(cpu)
(recevice,send,allflow)=adb.getflow()
receflow = '下載流量:' + str(int(recevice[-1]))
sendflow = '上傳流量:' + str(int(send[-1]))
alladd = '總流量:' + str(int(allflow[-1]))
self.ui.recv.append(receflow)
self.ui.send.append(sendflow)
self.ui.all.append(alladd)
點擊開始按鈕,啟動定時器,并使開始按鈕失效
def startTimer(self):
'''
設置時間間隔并啟動定時器
:return:
'''
self.timer.start(self.wait_time())
self.ui.start.setEnabled(False)
self.ui.end.setEnabled(True)
點擊結(jié)束按鈕,停止定時器,并使開始按鈕生效。
def endTimer(self):
self.timer.stop()
self.ui.start.setEnabled(True)
Matplotlib的應用
Matplotlib是python常用的繪圖模塊,提供了一套與MATLAB 相似的命令API,用來交互式的繪圖,非常方便。
設置繪圖類
新增一個MatplotlibWidget.py文件,創(chuàng)建FigureCanvas類,在初始化過程中建立一個空白圖像。
class MyMplCanvas(FigureCanvas):
"""FigureCanvas的最終的父類其實是QWidget。"""
def __init__(self, parent=None, width=5, height=4, dpi=100):
# 配置中文顯示
plt.rcParams['font.family'] = ['SimHei'] # 用來正常顯示中文標簽
plt.rcParams['axes.unicode_minus'] = False # 用來正常顯示負號
self.fig = plt.figure(figsize=(width, height), dpi=dpi) # 新建一個figure
self.axes = self.fig.add_subplot(111) # 建立一個子圖,如果要建立復合圖,可以在這里修改
self.axes.hold(False) # 每次繪圖的時候不保留上一次繪圖的結(jié)果
FigureCanvas.__init__(self, self.fig)
self.setParent(parent)
'''定義FigureCanvas的尺寸策略,這部分的意思是設置FigureCanvas,使之盡可能的向外填充空間。'''
FigureCanvas.setSizePolicy(self,
QSizePolicy.Expanding,
QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
定義繪圖函數(shù),調(diào)用這個函數(shù)可以在上面所創(chuàng)建的空白圖像中繪圖。
def start_static_plot(self):
self.fig.suptitle('圖表')
a=[1,2,4,2,3,1,2,3,4,2]
self.axes.plot(a)
self.axes.set_ylabel('number')
self.axes.grid(True)
封裝繪圖類
這部分主要把上面的繪圖類和工具欄封裝到MatplotlibWidget中,只需要調(diào)用MatplotlibWidget這個類就可以實現(xiàn)繪圖功能;
class MatplotlibWidget(QWidget):
def __init__(self, parent=None):
super(MatplotlibWidget, self).__init__(parent)
self.initUi()
def initUi(self):
self.layout = QVBoxLayout(self)
self.mpl = MyMplCanvas(self, width=5, height=4, dpi=100)
self.mpl.start_static_plot()
self.mpl_ntb = NavigationToolbar(self.mpl, self) # 添加完整的 toolbar
self.layout.addWidget(self.mpl)
self.layout.addWidget(self.mpl_ntb)
測試程序:
if __name__ == '__main__':
app = QApplication(sys.argv)
ui = MatplotlibWidget()
ui.mpl.start_static_plot() # 測試靜態(tài)圖效果
ui.show()
sys.exit(app.exec_())
結(jié)果運行,如圖所示:

設置提升窗口控件
在QT Designer中右擊提升窗口部件,新建一個QWidget類,名稱和頭文件均為 MatplotlibWidget

在.ui文件中加入widget并升級

MatplotlibWidget的使用
首先初始化模型:
class Main(QMainWindow,Ui_Form):
def __init__(self,parent=None):
super(Main,self).__init__(parent)
self.ui = Ui_Form()
self.ui.setupUi(self)
self.setWindowTitle('Waiqin365-AATT-V1.1.0')
self.ui.mem_plot.setVisible(False)
初始化中隱藏圖像,設置按鈕的出發(fā)操作,同時使得圖像可見并出發(fā)繪圖函數(shù)
@pyqtSlot()
def on_pushButton_clicked(self):
self.ui.mem_plot.setVisible(True)
self.ui.mem_plot.mpl.start_static_plot()
測試程序:
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
ui = Main()
ui.show()
sys.exit(app.exec_())
運行結(jié)果如下所示:

思考
雖然工具優(yōu)化到V1.1.0版本,但是仍存在很多不足的情況,目前遇到的問題:
1.打包成exe文件后,無法使用
2.缺少對手機狀態(tài)的監(jiān)控,斷開連接后,沒有自動停止
3.還不能動態(tài)展示圖表
后面有時間將一一攻破這些難題,歡迎有ideal的小伙伴多提提意見