1.界面设计
1.1 环境配置
在外部工具位置进行配置
1.2 UI界面设计
1.2.1 进入QT的UI设计界面
在pycharm中按顺序点击,进入UI编辑界面:
点击第三步后进入QT的UI设计界面,通过点击按钮进行界面设计,设计后进行保存到当前Pycharm项目的文件路径之下。
1.2.2 .ui文件转换为.py文件
1.2.3 运行主程序
通过以下代码对ui转换的py文件进行调用:
# -*- coding: utf-8 -*-
import smtplib
import ssl
from email.mime.text import MIMEText
from email.header import Header
from email.utils import formataddrimport sys
from PyQt5.QtWidgets import QApplication,QMainWindow
from EmailSenderUI import Ui_Form # 加载布局# 定义主窗口类,继承自QMainWindow和自动生成的UI类Ui_Form
class Mywindow(QMainWindow, Ui_Form):def __init__(self): # 调用父类QMainWindow的初始化方法super().__init__() # 初始化UI界面(由Qt Designer生成的setupUi方法)self.setupUi(self) # 可在此处添加额外的初始化代码(如信号槽连接等)if __name__ == '__main__':# 当直接运行本脚本时执行以下代码(而非被其他模块导入时)app = QApplication(sys.argv) # 创建Qt应用程序实例,sys.argv用于传递命令行参数ui = Mywindow() # 实例化主窗口对象ui.show() # 显示主窗口sys.exit(app.exec_()) # 进入Qt主事件循环,等待用户操作。sys.exit()确保程序能正确退出并返回状态码
运行结果如下图所示:
注:通过上面的步骤就可以得到一个设计的初始化界面,其具体功能还未实现。
1.3 功能实现——槽函数
UI界面设计的各个控件的名称通过槽函数与相应的功能函数进行连接
2. 完整代码
程序共包含4个文件:main.py,open_show_file.py,发送邮件函数.py,EmailSenderUI.py
2.1 open_show_file.py
import sys
import pandas as pd
from PyQt5.QtWidgets import QApplication,QMainWindowfrom PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QPushButton, QLabel, QFileDialog, QTextEdit,QTableWidget, QTableWidgetItem, QWidget,QStackedWidget
from sklearn.ensemble import RandomForestRegressor
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtCore import Qtfrom sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error, mean_absolute_error
from sklearn.metrics import *
import numpy as npimport torch
import torch.nn as nn
import torch.optim as optim
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, mean_absolute_errorimport matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
## 设置字符集,防止中文乱码
import matplotlib as mpl #画图工具
mpl.rcParams['font.sans-serif']=[u'simHei']
mpl.rcParams['axes.unicode_minus']=False############################################################################## page1_1_1 ####################################################################################
# 打开文件,选择路径并显示
def open_select_file_def(parent,page1_1_1_via_show):options = QFileDialog.Options() # 创建一个文件对话框选项对象。options |= QFileDialog.ReadOnly # 将选项设置为只读模式,这表示用户只能选择已经存在的文件而不能创建新文件。file_path, _ = QFileDialog.getOpenFileName(parent, "Select File", "", "Excel Files (*.xlsx *.xls)", options=options)# 调用文件对话框的getOpenFileName方法,该方法会打开文件选择对话框 ;参数:# self:表示当前窗口或部件。# "Select File":对话框标题。# "":默认路径,此处为空字符串表示打开对话框时不指定默认路径。# "Excel Files (*.xlsx)":文件类型过滤器,限制用户只能选择Excel文件。# options = options:传递前面创建的选项对象。if file_path: # 检查用户是否选择了文件路径,如果选择了文件,则进入下面的代码块。selected_file_path = file_path # 将选择的文件路径保存到对象的 selected_file_path 属性中,以便后续使用。page1_1_1_via_show.setText(f"文件路径: {file_path}") # 将界面上的文件标签的文本设置为显示所选文件的路径。page1_1_1_data = pd.read_excel(file_path) # 使用 pandas 读取 Excel 文件数据return page1_1_1_dataelse:pass# 将 Excel 数据填充到表格中。
def show_file_data_def(table_widget, data):table_widget.setColumnCount(data.shape[1]) # 将表格小部件的列数设置为data DataFrame的列数,以便为每个数据行创建一个对应的表格列table_widget.setRowCount(data.shape[0]) # 将表格小部件的行数设置为data DataFrame的行数,以便为每个数据行创建一个对应的表格行table_widget.setHorizontalHeaderLabels(data.columns) # 将DataFrame的列名设置为表格小部件的水平表头标签for row_idx in range(data.shape[0]):for col_idx in range(data.shape[1]):item = QTableWidgetItem(str(data.iat[row_idx, col_idx])) # 从DataFrame中获取特定行和列索引位置处的单元格数据,并使用str()函数将其转换为字符串。然后,通过QTableWidgetItem()将该字符串添加到表格小部件的特定单元格中。table_widget.setItem(row_idx, col_idx, item) # 将 QTableWidgetItem 对象放置到表格小部件的特定单元格中,从而将数据显示在表格中
############################################################################## page1_1_1 ####################################################################################
2.2 发送邮件函数.py:
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
import osimport pandas as pddef send_email(from_addr,password,to_addrs,subject,body,attachments=None,smtp_server="smtp.qq.com",smtp_port=587
):msg = MIMEMultipart()msg["From"] = from_addrmsg["To"] = ",".join(to_addrs)msg["Subject"] = subjectmsg.attach(MIMEText(body, "plain", "utf-8"))# 添加附件if attachments:for file_path in attachments:part = MIMEBase("application", "octet-stream")with open(file_path, "rb") as f:part.set_payload(f.read())encoders.encode_base64(part)part.add_header("Content-Disposition",f"attachment; filename={os.path.basename(file_path)}",)msg.attach(part)server = smtplib.SMTP(smtp_server, smtp_port)server.starttls()try:server.login(from_addr, password)except Exception as e:return "登录失败","请输入正确的邮箱账号和授权码"try:server.sendmail(from_addr,to_addrs,msg.as_string())# print(f"邮件 {to_addrs} 发送成功!")return f"{to_addrs} ","成功"except Exception as e:# print(f"发送失败:{str(e)}")# print(f"邮件 {to_addrs} 发送失败!")return f"{to_addrs} ","失败"finally:server.quit()
2.3 main.py:
# -*- coding: utf-8 -*-
import smtplib
import ssl
from email.mime.text import MIMEText
from email.header import Header
from email.utils import formataddr
import pandas as pd
import sys
from PyQt5.QtWidgets import QApplication,QMainWindow
from EmailSenderUI import Ui_Form # 加载布局
from 软件功能函数.open_show_file import open_select_file_def,show_file_data_def
from 软件功能函数.发送邮件函数 import send_emailfrom PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QPushButton, QLabel, QFileDialog, QTextEdit, \QTableWidget, QTableWidgetItem, QWidget,QStackedWidget
from sklearn.ensemble import RandomForestRegressor
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtCore import Qtfrom sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error, mean_absolute_error
from sklearn.metrics import *
import numpy as npimport torch
import torch.nn as nn
import torch.optim as optim
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, mean_absolute_errorimport matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
## 设置字符集,防止中文乱码
import matplotlib as mpl #画图工具import rempl.rcParams['font.sans-serif']=[u'simHei']
mpl.rcParams['axes.unicode_minus']=False# 定义主窗口类,继承自QMainWindow和自动生成的UI类Ui_Form
class Mywindow(QMainWindow, Ui_Form):def __init__(self): # 调用父类QMainWindow的初始化方法super().__init__() # 初始化UI界面(由Qt Designer生成的setupUi方法)self.setupUi(self) # 可在此处添加额外的初始化代码(如信号槽连接等)# 通过槽函数 将控件名称与功能实现函数连接self.pushButton_open.clicked.connect(self.button_open_file) # 连接 pushButton_open 钮到 button_open_file 函数方法self.pushButton_confirm.clicked.connect(self.email_information)self.pushButton_send.clicked.connect(self.send_information)# 函数功能实现# 打开文件夹,获取接收方账号等信息def button_open_file(self):self.data_frame = open_select_file_def(self, self.lineEdit_via_show)show_file_data_def(self.email_show, self.data_frame)# 确实邮件发送方信息def email_information(self):try:self.EmailAccount_text = self.sender_email.text().strip() # 获取文本内容,并去除首位空格self.EmailCode_text = self.sender_email_code.text().strip() # 获取文本内容if not self.EmailAccount_text or not self.EmailCode_text:self.label_information.setText("请确认发送方账号和验证码的输入信息")return# 邮箱格式验证(正则表达式)if not re.match(r'^[\w\.-]+@[\w\.-]+\.\w+$', self.EmailAccount_text):self.label_information.setText("发送方的邮箱格式不正确")returnelse:self.label_information.setText("发送方账号和验证码输入成功")# 此处可添加后续逻辑(如调用发送邮件函数)except Exception as e:print(f"信息读取错误: {str(e)}") # 明确打印错误类型# 发送邮件def send_information(self):sender_account = self.EmailAccount_textsender_password = self.EmailCode_textresults = []for index, row in self.data_frame.iterrows():# 提取当前行数据to_email = row.iloc[0]subject = row.iloc[1]body = row.iloc[2]result = send_email(from_addr=sender_account, password=sender_password, to_addrs=to_email, subject=subject,body=body)results.append(result)# 设置表格的行数和列数self.email_send_information.setRowCount(len(results))self.email_send_information.setColumnCount(2) # 假设有三个字段:Name, Age, City# 设置表头self.email_send_information.setHorizontalHeaderLabels(["邮箱账号","邮件发送状态"])# 填充数据for row, row_data in enumerate(results):self.email_send_information.setItem(row, 0, QTableWidgetItem(str(row_data[0])))self.email_send_information.setItem(row, 1, QTableWidgetItem(str(row_data[1])))if __name__ == '__main__':# 当直接运行本脚本时执行以下代码(而非被其他模块导入时)app = QApplication(sys.argv) # 创建Qt应用程序实例,sys.argv用于传递命令行参数ui = Mywindow() # 实例化主窗口对象ui.show() # 显示主窗口sys.exit(app.exec_()) # 进入Qt主事件循环,等待用户操作。sys.exit()确保程序能正确退出并返回状态码
2.4 EmailSenderUI.py
# -*- coding: utf-8 -*-# Form implementation generated from reading ui file 'EmailSenderUI.ui'
#
# Created by: PyQt5 UI code generator 5.12
#
# WARNING! All changes made in this file will be lost!from PyQt5 import QtCore, QtGui, QtWidgetsclass Ui_Form(object):def setupUi(self, Form):Form.setObjectName("Form")Form.resize(778, 827)self.pushButton_open = QtWidgets.QPushButton(Form)self.pushButton_open.setGeometry(QtCore.QRect(60, 30, 101, 41))self.pushButton_open.setObjectName("pushButton_open")self.lineEdit_via_show = QtWidgets.QLineEdit(Form)self.lineEdit_via_show.setGeometry(QtCore.QRect(190, 30, 471, 41))self.lineEdit_via_show.setObjectName("lineEdit_via_show")self.sender_email = QtWidgets.QLineEdit(Form)self.sender_email.setGeometry(QtCore.QRect(70, 310, 461, 41))self.sender_email.setText("")self.sender_email.setObjectName("sender_email")self.pushButton_confirm = QtWidgets.QPushButton(Form)self.pushButton_confirm.setGeometry(QtCore.QRect(560, 320, 91, 91))self.pushButton_confirm.setObjectName("pushButton_confirm")self.sender_email_code = QtWidgets.QLineEdit(Form)self.sender_email_code.setGeometry(QtCore.QRect(70, 390, 461, 41))self.sender_email_code.setText("")self.sender_email_code.setObjectName("sender_email_code")self.label = QtWidgets.QLabel(Form)self.label.setGeometry(QtCore.QRect(80, 280, 131, 31))self.label.setObjectName("label")self.label_2 = QtWidgets.QLabel(Form)self.label_2.setGeometry(QtCore.QRect(80, 360, 191, 31))self.label_2.setObjectName("label_2")self.email_show = QtWidgets.QTableWidget(Form)self.email_show.setGeometry(QtCore.QRect(60, 80, 601, 192))self.email_show.setObjectName("email_show")self.email_show.setColumnCount(0)self.email_show.setRowCount(0)self.email_send_information = QtWidgets.QTableWidget(Form)self.email_send_information.setGeometry(QtCore.QRect(60, 570, 591, 171))self.email_send_information.setObjectName("email_send_information")self.email_send_information.setColumnCount(0)self.email_send_information.setRowCount(0)self.pushButton_send = QtWidgets.QPushButton(Form)self.pushButton_send.setGeometry(QtCore.QRect(60, 520, 591, 41))self.pushButton_send.setObjectName("pushButton_send")self.label_information = QtWidgets.QLabel(Form)self.label_information.setGeometry(QtCore.QRect(80, 460, 571, 41))self.label_information.setObjectName("label_information")self.retranslateUi(Form)QtCore.QMetaObject.connectSlotsByName(Form)def retranslateUi(self, Form):_translate = QtCore.QCoreApplication.translateForm.setWindowTitle(_translate("Form", "Form"))self.pushButton_open.setText(_translate("Form", "打开"))self.pushButton_confirm.setText(_translate("Form", "确认"))self.label.setText(_translate("Form", "发送方的邮箱账号:"))self.label_2.setText(_translate("Form", "发送方的邮箱账号的授权码:"))self.pushButton_send.setText(_translate("Form", "发送"))self.label_information.setText(_translate("Form", "信息:"))
2.5 文件目录结构
2.6 程序运行界面
获取邮箱授权码_qq邮箱授权码如何获取-CSDN博客文章浏览阅读1.6k次。登录QQ邮箱:依次点击:设置--账号。_qq邮箱授权码如何获取https://blog.csdn.net/javin4715/article/details/140911566?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522b863bb97086e7c2892e63c5833317f87%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=b863bb97086e7c2892e63c5833317f87&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-1-140911566-null-null.142^v102^pc_search_result_base7&utm_term=qq%E9%82%AE%E7%AE%B1%E6%8E%88%E6%9D%83%E7%A0%81&spm=1018.2226.3001.4187
3. 代码打包成APP
使用下面代码在终端进行打包:
pyinstaller -F -w app.py -n xxx # 其中app.py为你的.py代码名字; xxx 为打包时设置的软件名字
pyinstaller -F -w main.py -n EmailQQ
其中:打包时会自动去添加需要的代码,因此app.py为主函数代码。如下图所示:
当生成完成后,将会在项目的文件路径下看到多了3个文件build、 dist 、app.spec,其中在dist目录下看到有一个 EmailQQ.exe 文件,这就是使用 PyInstaller 工具生成的 EXE 程序。
打包方法介绍https://blog.csdn.net/qq_68639191/article/details/136215464?spm=1011.2415.3001.5331