title: PyQt5桌面开发实例
date: 2020-03-16 12:30:05
categories:
- Python
tags:
- 桌面开发
- PyQt
cover: https://antrovirens-1-1258258000.cos.ap-shanghai.myqcloud.com/cloud/%E9%9C%B2%E7%B1%B3%E5%A8%85.png
P.S. 发现我啥时候把nodejs给卸掉了…
已知坐标,计算AB两点间距离和方位角,输出结果
设计ui - 编译ui - 编写函数与响应 - 打包exe
一个menu,两个下拉单,
self.menu
self.action_Open
self.action_Save
self.action_Close
self.action_Quit
self.menu_2
self.action_Calculate
6个lineEdit用来输入和输出结果 ,1个plainTextEdit作为进程提示,1个graphicsView输出图形
self.lineEdit_XA
self.lineEdit_XB
self.lineEdit_YA
self.lineEdit_YB
self.lineEdit_Sab
self.lineEdit_tab
self.plainTextEdit
self.graphicsView
测试数据文件
1,2
3,4
头文件
import sys
from math import pi, atan, sqrt
from datetime import datetime #输出时间
import matplotlib
matplotlib.use("Qt5Agg") # 声明使用QT5
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtGui import * #这里懒得改了
from PyQt5.QtWidgets import *
from Ui_MainWindow import Ui_MainWindow
主函数
if __name__ == '__main__':
app = QApplication(sys.argv)
dlg = MainWindow()
dlg.show()
sys.exit(app.exec_())
初始化为float
x = [0.0, 0.0]
y = [0.0, 0.0]
Sab = 0.0
Tab = 0.0
计算方位角(高斯平面坐标系)
def Azimuth():
dx = x[1] - x[0]
dy = y[1] - y[0]
if dx ==0:
if dy >=0 :
a = pi/2
else:
a = pi * 3 / 2
elif dy ==0:
if dx >= 0:
a=0
else:
a = pi
else:
a = atan(dy / dx)
if dx <= 0:
a = a + pi
elif dy <= 0:
a = a + 2 * pi
return a
quit
@pyqtSlot()
def on_action_Quit_triggered(self):
self.close()
推荐用with as格式写
@pyqtSlot()
def on_action_Open_triggered(self):
filename,_ = QFileDialog.getOpenFileName(self, '输入坐标数据', './', 'All Files (*);;Text Files (*.txt)');
if filename == '':
self.plainTextEdit.appendPlainText('[' + str(datetime.now()) + ']' + '打开失败 返回值为空')
return 0
f=open(filename,'r', encoding='utf-8')
dic = []
for line in f.readlines():
line=line.strip('\n') #去掉换行符\n
b=line.split(',') #将每一行以空格为分隔符转换成列表
dic.append(b)
self.lineEdit_XA.setText(dic[0][0])
self.lineEdit_YA.setText(dic[0][1])
self.lineEdit_XB.setText(dic[1][0])
self.lineEdit_YB.setText(dic[1][1])
self.plainTextEdit.appendPlainText('[' + str(datetime.now()) + ']' + '打开文件:' + str(filename))
f.close()
@pyqtSlot()
def on_action_Save_triggered(self):
"""
Slot documentation goes here.
"""
# TODO: 保存结果
with open('输出结果.txt','a') as f:
f.write('[' + str(datetime.now()) + ']' + '\n')
f.write('A:'+str([x[0], y[0]]) + ';B:' + str([x[1],y[1]]) + '\n')
f.write('Sab = '+ str(Sab) + '; Tab = ' + str(Tab) + '\n')
f.write('\n')
self.plainTextEdit.appendPlainText('[' + str(datetime.now()) + ']' + '保存成功')
# TODO: 检查是否缺失条件, 进行计算, 绘制图形
if self.lineEdit_XA.text() == '' or self.lineEdit_XB.text() == '' or self.lineEdit_YA.text() == '' or self.lineEdit_YB.text() == '': #空的情况下,内容为‘’ (空白);不是None
self.plainTextEdit.appendPlainText('[' + str(datetime.now()) + ']' + '中断:参数为空')
return 0
XA = float(self.lineEdit_XA.text())
XB = float(self.lineEdit_XB.text())
YA = float(self.lineEdit_YA.text())
YB = float(self.lineEdit_YB.text())
if XA ==XB and YA == YB:
self.plainTextEdit.appendPlainText('[' + str(datetime.now()) + ']' + '中断:两点重合')
return 0
global x, y, Sab, Tab # 给全局变量赋值
x = [XA, XB]
y = [YA, YB]
Sab = sqrt((XA - XB) * (XA - XB) + (YA - YB) * (YA - YB) )
Tab = Azimuth()
self.lineEdit_Sab.setText(str(Sab))
self.lineEdit_tab.setText(str(Tab))
self.plainTextEdit.appendPlainText('[' + str(datetime.now()) + ']' + '计算完成:' + 'Sab = '+ str(Sab) + '; Tab = ' + str(Tab))
这个还有点麻烦,参考的是这个人的代码(Matplotlib植入PyQt5 + QT5的UI呈现):https://www.cnblogs.com/laoniubile/p/5904817.html
写了一个类来实现把figure给传递出去
class Figure_Canvas(FigureCanvas): # 通过继承FigureCanvas类,使得该类既是一个PyQt5的Qwidget,又是一个matplotlib的FigureCanvas,这是连接pyqt5与matplot lib的关键
def __init__(self, parent=None, width=5.1, height=4, dpi=10):
fig = Figure(figsize=(width, height), dpi=80) # 创建一个Figure,注意:该Figure为matplotlib下的figure,不是matplotlib.pyplot下面的figure
FigureCanvas.__init__(self, fig) # 初始化父类
self.setParent(parent)
self.axes = fig.add_subplot(111) # 调用figure下面的add_subplot方法,类似于matplotlib.pyplot下面的subplot方法
def StartPlot(self):
self.axes.set_xlabel('Y')
self.axes.set_ylabel('X')
self.axes.scatter(y[0], x[0], c= 'red', marker='o')
self.axes.scatter(y[1], x[1], c= 'yellow')
self.axes.legend(('A', 'B'), loc='best')
self.axes.set_title('Calculation Results',color = 'blue')
self.axes.plot(y, x, c= 'blue', lw=0.5)
self.axes.annotate('(' + str(x[0]) + ',' + str(y[0]) + ')', xy=(y[0], x[0]), xytext=(-40, 6), textcoords='offset points', weight='heavy')
self.axes.annotate('(' + str(x[1]) + ',' + str(y[1]) + ')', xy=(y[1], x[1]), xytext=(-40, 6), textcoords='offset points', weight='heavy')
t1 = (y[0]+y[1])/2
t2 = (x[0]+x[1])/2
self.axes.annotate('Sab = '+ str(Sab) + '; Tab = ' + str(Tab), xy=(t1, t2), xytext=(-80, 80), textcoords='offset points', color = 'blue', arrowprops = dict( arrowstyle = '->', connectionstyle = 'arc3', color = 'b'))
用QGraphicsScene来加载figure,然后在View显示
ins = Figure_Canvas() #实例化一个FigureCanvas
ins.StartPlot() # 画图
graphicscene = QGraphicsScene() #创建一个QGraphicsScene,因为加载的图形(FigureCanvas)不能直接放到graphicview控件中,必须先放到graphicScene,然后再把graphicscene放到graphicview中
graphicscene.addWidget(ins) # 把图形放到QGraphicsScene中,注意:图形是作为一个QWidget放到QGraphicsScene中的
# graphicscene=graphicscene.scaled(self.graphicsView.width()-10,self.graphicsView.height()-10)
# 咋调大小暂时还没搞清楚
self.graphicsView.setScene(graphicscene) # 把QGraphicsScene放入QGraphicsView
self.graphicsView.show() # 调用show呈现图形
贴一个upx win64的下载链接,我自己上传的,官网下载巨慢,把upx扔到scrips下面就会自动使用,有时候会缺一些奇怪的东西,咋解决还没搞明白:https://www.lanzous.com/iabcmxi
感觉写个程序自己用用就行了,打包交作业实属憨憨,,特么生成出来200m,怕不是把整个qt整进去了
在文件夹里面按住shift右键,打开powershell,是个命令行就行
pyinstaller -F filename #生成单个exe文件,比较小 -D为生成dll文件和一个exe文件,整个文件夹巨几儿大
然后会多两文件夹和一个spec文件,build里面是生成的中间文件,dist里面是生成的程序文件,spec文件里面可以手动修改生成选项
怎么优化可以看看这个文章(pyinstaller打包的exe太大?你需要嵌入式python玄学 拓展篇):https://zhuanlan.zhihu.com/p/77317765
莫得总结
结果文件
[2020-03-16 15:20:07.085889]
A:[1.0, 1.0];B:[1.0, 2.0]
Sab = 1.0; Tab = 1.5707963267948966