前言
上一篇文章介绍了工具的数据采集部分,这段时间对工具页面进行了优化:
- 增加清屏功能
- 增加图表显示
新版本V1.1.0界面如下所示:
工具介绍
使用方法介绍
使用方法上一篇文章,已经大致介绍过了,主要步骤如下:
(电脑环境配置什么的就不在赘述了)
- 连接手机,点击检查设备,正常获取返回设备SN号,获取失败,显示‘No device found’
- 打开待测应用,点击获取,获取应用包名和activity
- 下拉选择更新时间
- 开始测试,结束
- 点击图表,显示图表(这边暂时未做到实时显示图表,后续再优化)
主界面介绍
基于QT Designer工具,添加需要的pushbutton、textedit等控件,这个上一篇文章已经介绍过了,QT Designer的简单使用,就不再多说了。
这篇文章就重点说一下核心代码部分和遇到的问题及解决方法吧。
过程中主要遇到了两个问题:
1.数据采集过程中,需要在保留原有数据的基础上,不断添加新数据
2.图表的展示
流量的统计
数据采集部分,主要代码如下:
采用
adb shell cat /proc/net/xt_qtaguid/stats | findstr uid
命令获取到的流量是一个total值,而我们需要统计的是一段时间内的值,所以这边采用两个值相减的方法,即根据选择的更新时间,后一个减去前一个的结果,得到这段时间内的统计值
#获取流量
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主要是为了解决,在写数据的过程中,不断往原有数据上append新采集到数据的问题,同时不至于是应用无响应。
初始化一个定时器,把定时器的timeout信号和slotadd()槽函数连接。
self.timer = QTimer(self)
self.timer.timeout.connect(self.slotadd)
slotadd()往五个textedit中写数据
由于返回的数据是一个列表,所以每次只需要取最新的即最后一个数据即可。
def slotadd(self):
'''
往mem、cpu、flow写数据
: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)
点击结束按钮,停止定时器,并使开始按钮生效。
def endTimer(self):
self.timer.stop()
self.ui.start.setEnabled(True)
Matplotlib的应用
Matplotlib是python常用的绘图模块,提供了一套与MATLAB 相似的命令API,用来交互式的绘图,非常方便。
设置绘图类
新增一个MatplotlibWidget.py文件,创建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) # 每次绘图的时候不保留上一次绘图的结果
FigureCanvas.__init__(self, self.fig)
self.setParent(parent)
'''定义FigureCanvas的尺寸策略,这部分的意思是设置FigureCanvas,使之尽可能的向外填充空间。'''
FigureCanvas.setSizePolicy(self,
QSizePolicy.Expanding,
QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
定义绘图函数,调用这个函数可以在上面所创建的空白图像中绘图。
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中,只需要调用MatplotlibWidget这个类就可以实现绘图功能;
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() # 测试静态图效果
ui.show()
sys.exit(app.exec_())
结果运行,如图所示:
设置提升窗口控件
在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)
初始化中隐藏图像,设置按钮的出发操作,同时使得图像可见并出发绘图函数
@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_())
运行结果如下所示:
思考
虽然工具优化到V1.1.0版本,但是仍存在很多不足的情况,目前遇到的问题:
1.打包成exe文件后,无法使用
2.缺少对手机状态的监控,断开连接后,没有自动停止
3.还不能动态展示图表
后面有时间将一一攻破这些难题,欢迎有ideal的小伙伴多提提意见