欢迎关注 『pyqt5 从0基础开始项目实战』 专栏,持续更新中
欢迎关注 『pyqt5 从0基础开始项目实战』 专栏,持续更新中
导包和框架代码
上一文遗留的代码
import os
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QDesktopWidget, QHBoxLayout, QVBoxLayout
from PyQt5.QtWidgets import QPushButton, QLineEdit, QTableWidget, QTableWidgetItem, QLabel
class MainWindow(QWidget):
def __init__(self):
# 用super 继承父类的初始化
super().__init__()
# 设置窗口的窗体标题
self.setWindowTitle('发现你走远了的xx系统')
# 设置窗体的尺寸
self.resize(1228, 450)
# 设置窗体位置
# 获取整个窗口部分的宽高和左上角坐标信息,返回值是一个QRect类型,(x,y width,height)
qr = self.frameGeometry()
cp = QDesktopWidget().availableGeometry().center() # 得到屏幕中间的位置信息
qr.moveCenter(cp) # 让我们的窗体移动到屏幕中间
# 创建窗口总布局
layout = QVBoxLayout()
# 讲调用方法生成的顶部菜单布局添加到总布局
layout.addLayout(self.init_header())
layout.addLayout(self.init_form())
layout.addLayout(self.init_table())
layout.addLayout(self.init_footer())
# 给窗体设置元素的排列方式
self.setLayout(layout)
def init_header(self):
# 1.顶部菜单布局
header_layout = QHBoxLayout() # 创建顶部菜单布局
# 1.1 放入按钮
btn_start = QPushButton("开始") # 新建一个开始按钮
header_layout.addWidget(btn_start) # 将开始按钮添加到顶部菜单布局
btn_stop = QPushButton("停止") # 新建一个开始按钮
header_layout.addWidget(btn_stop) # 将开始按钮添加到顶部菜单布局
# 1.2 加入弹簧
header_layout.addStretch()
return header_layout
def init_form(self):
# 2.添加内容布局
form_layout = QHBoxLayout() # 创建添加内容布局
# 2.1 输入框
txt_asin = QLineEdit() # 新建一个输入框对象
txt_asin.setText("B07YN82X3B=100") # 设置默认的form数据
txt_asin.setPlaceholderText("请输入商品ID和价格,例如:B0818JJQQ8=88") # 设置灰色的提示信息
form_layout.addWidget(txt_asin) # 将输入框加入到布局中
# 2.2 添加按钮
btn_add = QPushButton("添加") # 新建一个添加按钮
form_layout.addWidget(btn_add) # 将添加按钮添加到form布局
return form_layout
def init_table(self):
# 3.表格数据展示布局
table_layout = QHBoxLayout()
# 3.1 创建表格
table_widget = QTableWidget(0, 8) # 新建一个0行8列的表格
# # 修改表格索引名
# item=QTableWidgetItem()
# item.setText("标题0")
# table_widget.setHorizontalHeaderItem(0,item)
# table_widget.setColumnWidth(0,150)#设置水平单元格0号位置的宽度 150
#
# item2=QTableWidgetItem()
# item2.setText("网址1")
# table_widget.setHorizontalHeaderItem(1,item2)
# table_widget.setColumnWidth(1,400)#设置水平单元格1号位置的宽度 400
#
# item3=QTableWidgetItem()
# item3.setText("行索引0")
# table_widget.setVerticalHeaderItem(0,item3)
table_header = [
{"field": "asin", "text": "ASIN", 'width': 120},
{"field": "title", "text": "标题", 'width': 150},
{"field": "url", "text": "URL", 'width': 400},
{"field": "price", "text": "底价", 'width': 100},
{"field": "success", "text": "成功次数", 'width': 100},
{"field": "error", "text": "503次数", 'width': 100},
{"field": "status", "text": "状态", 'width': 100},
{"field": "frequency", "text": "频率(N秒/次)", 'width': 100},
]
for idx, info in enumerate(table_header):
item = QTableWidgetItem()
item.setText(info['text'])
table_widget.setHorizontalHeaderItem(idx, item)
table_widget.setColumnWidth(idx, info['width'])
table_layout.addWidget(table_widget) # 把表格添加到表格布局中
return table_layout
def init_footer(self):
# 4.底部菜单
footer_layout = QHBoxLayout()
label_status = QLabel("未检测", self)
footer_layout.addWidget(label_status)
footer_layout.addStretch() # 添加弹簧,更加美观
btn_reset = QPushButton("重新初始化")
footer_layout.addWidget(btn_reset)
btn_recheck = QPushButton("重新检测")
footer_layout.addWidget(btn_recheck)
btn_reset_count = QPushButton("次数清零")
footer_layout.addWidget(btn_reset_count)
btn_delete = QPushButton("删除检测项")
footer_layout.addWidget(btn_delete)
btn_alert = QPushButton("SMTP报警配置")
footer_layout.addWidget(btn_alert)
btn_proxy = QPushButton("代理IP")
footer_layout.addWidget(btn_proxy)
return footer_layout
if __name__ == '__main__':
app = QApplication(sys.argv) # 实例化一个Application应用,所有的窗口均在其下运行
window = MainWindow() # 实例化窗口对象
window.show() # 窗口展示
sys.exit(app.exec_())
# app.exec_()运行主循环,并在退出时返回状态代码。
# sys.exit(n)退出您的应用程序并返回n到父进程(通常是您的shell)
准备json数据文件
在py文件同级目录下新建一个db文件夹,文件夹下放置db.json的数据文件
db.json内容如下,你可以自己新建然后复制黏贴即可:
[
["B08166SLDF", "AMD Ryzen 5 5600X 6-core, 12-Thread Unlocked Desktop Processor with Wraith Stealth Cooler", "https://www.amazon.com/gp/offer-listing/B08166SLDF/ref=dp_olp_all_mbc?ie=UTF8&condition=new", 300.0, 0, 166, 1, 5],
["B07YN82X3B", "Logitech G203 Wired Gaming Mouse, 8,000 DPI, Rainbow Optical Effect LIGHTSYNC RGB, 6 Programmable Buttons, On-Board Memory, Screen Mapping, PC/Mac Computer and Laptop Compatible - Black", "https://www.amazon.com/gp/offer-listing/B07YN82X3B/ref=dp_olp_all_mbc?ie=UTF8&condition=new", 1111.0, 0, 172, 1, 5],
["B07W6JN8N7", "Logitech G203 Lightsync Gaming Mouse with Customizable RGB Lighting, 6 Programmable Buttons, Gaming Grade Sensor, 8 k dpi Tracking, Light Weight (White)", "https://www.amazon.com/gp/offer-listing/B07W6JN8N7/ref=dp_olp_all_mbc?ie=UTF8&condition=new", 123123.0, 0, 168, 1, 5],
["B07MN1VBKD", "HP Chromebook 14-inch Laptop with 180-Degree Hinge, AMD Dual-Core A4-9120 Processor, 4 GB SDRAM, 32 GB eMMC Storage, Chrome OS (14-db0030nr, Snow White)", "https://www.amazon.com/gp/offer-listing/B07MN1VBKD/ref=dp_olp_all_mbc?ie=UTF8&condition=new", 99999.0, 0, 168, 1, 5]
]
表格数据接入
1. 准备文件路径
先获取py文件所在的路径(以下称为主路径),然后用join
连接成主路径/db/db.json
先在import下面写上
BASE_DIR = os.path.dirname(os.path.realpath(sys.argv[0]))
#拿到在另外一台计算机上执行程序代码所存储的文件路径。
2. 读取json数据
# 读取数据文件
import json
file_path = os.path.join(BASE_DIR, "db", "db.json")
with open(file_path, mode='r', encoding='utf-8') as f:
data = f.read()
data_list = json.loads(data)#读取得到了json数据
3. 将得到的json数据放入table
current_row_count = table_widget.rowCount() # 当前表格有多少行
for row_list in data_list:#每有一行json数据,我们就需要遍历一轮增加一行数据
table_widget.insertRow(current_row_count)#增加一行
# print(row_list) # ['B08166SLDF', 'AMD er', 'https://www.amazon.', 300.0, 0, 166, 1, 5]
# 把row_list写入这一行
for i, ele in enumerate(row_list):#enumerate中 i表示索引id,ele表示数据值
cell = QTableWidgetItem(str(ele))#注意我们的数据格式转为str,比如说状态的数据可能本身是int类型
table_widget.setItem(current_row_count, i, cell)#写入数据到指定单元格
current_row_count += 1 #行数+1,这样下次遍历行时会在新的行下面新增一行
# 如果不新增行其实也可以用 current_row_count=table_widget.rowCount()替代
设置单元格不可修改
单元格对象.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) 设置单元格不可选中不可修改
current_row_count = table_widget.rowCount() # 当前表格有多少行
for row_list in data_list:#每有一行json数据,我们就需要遍历一轮增加一行数据
table_widget.insertRow(current_row_count)#增加一行
# print(row_list) # ['B08166SLDF', 'AMD er', 'https://www.amazon.', 300.0, 0, 166, 1, 5]
# 把row_list写入这一行
for i, ele in enumerate(row_list):#enumerate中 i表示索引id,ele表示数据值
cell = QTableWidgetItem(str(ele))#注意我们的数据格式转为str,比如说状态的数据可能本身是int类型
if i in [0, 4, 5, 6]:#如果是这几个索引值的单元格
# 不可修改
cell.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)#指定索引单元格不能选中和修改
table_widget.setItem(current_row_count, i, cell)#写入数据到指定单元格
current_row_count += 1 #行数+1,这样下次遍历行时会在新的行下面新增一行
# 如果不新增行其实也可以用 current_row_count=table_widget.rowCount()替代
- 价格可以修改
- 成功次数无法修改
把数据中的数字转为映射内容
比如说我们数据中的状态是数字 1 ,当然我们不想麻烦的查看数字1表示什么意思,不如直接显示一个“待处理”的汉字字符串。
首先在文件开头添加
STATUS_MAPPING = {
0: "初始化中",
1: "待执行",
2: "正在执行",
3: "完成并提醒",
10: "异常并停止",
11: "初始化失败",
}
然后新增一个判断复制的多目运算ele = STATUS_MAPPING[ele] if i == 6 else ele
current_row_count = table_widget.rowCount() # 当前表格有多少行
for row_list in data_list:#每有一行json数据,我们就需要遍历一轮增加一行数据
table_widget.insertRow(current_row_count)#增加一行
# print(row_list) # ['B08166SLDF', 'AMD er', 'https://www.amazon.', 300.0, 0, 166, 1, 5]
# 把row_list写入这一行
for i, ele in enumerate(row_list):#enumerate中 i表示索引id,ele表示数据值
# 一个多目运算 如果i==6(此时是状态的数据) 如果STATUS_MAPPING中能够找到ele的索引,那么我们把ele设置成STATUS_MAPPING中的内容
ele = STATUS_MAPPING[ele] if i == 6 else ele
cell = QTableWidgetItem(str(ele))#注意我们的数据格式转为str,比如说状态的数据可能本身是int类型
if i in [0, 4, 5, 6]:
# 不可修改
cell.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)#指定索引单元格不能选中和修改
table_widget.setItem(current_row_count, i, cell)#写入数据到指定单元格
current_row_count += 1 #行数+1,这样下次遍历行时会在新的行下面新增一行
# 如果不新增行其实也可以用 current_row_count=table_widget.rowCount()替代
完整代码
import os
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QDesktopWidget, QHBoxLayout, QVBoxLayout
from PyQt5.QtWidgets import QPushButton, QLineEdit, QTableWidget, QTableWidgetItem, QLabel
#拿到在另外一台计算机上执行程序代码所存储的文件路径。
BASE_DIR = os.path.dirname(os.path.realpath(sys.argv[0]))
STATUS_MAPPING = {
0: "初始化中",
1: "待执行",
2: "正在执行",
3: "完成并提醒",
10: "异常并停止",
11: "初始化失败",
}
class MainWindow(QWidget):
def __init__(self):
# 用super 继承父类的初始化
super().__init__()
# 设置窗口的窗体标题
self.setWindowTitle('发现你走远了的xx系统')
# 设置窗体的尺寸
self.resize(1228, 450)
# 设置窗体位置
# 获取整个窗口部分的宽高和左上角坐标信息,返回值是一个QRect类型,(x,y width,height)
qr = self.frameGeometry()
cp = QDesktopWidget().availableGeometry().center() # 得到屏幕中间的位置信息
qr.moveCenter(cp) # 让我们的窗体移动到屏幕中间
# 创建窗口总布局
layout = QVBoxLayout()
# 讲调用方法生成的顶部菜单布局添加到总布局
layout.addLayout(self.init_header())
layout.addLayout(self.init_form())
layout.addLayout(self.init_table())
layout.addLayout(self.init_footer())
# 给窗体设置元素的排列方式
self.setLayout(layout)
def init_header(self):
# 1.顶部菜单布局
header_layout = QHBoxLayout() # 创建顶部菜单布局
# 1.1 放入按钮
btn_start = QPushButton("开始") # 新建一个开始按钮
header_layout.addWidget(btn_start) # 将开始按钮添加到顶部菜单布局
btn_stop = QPushButton("停止") # 新建一个开始按钮
header_layout.addWidget(btn_stop) # 将开始按钮添加到顶部菜单布局
# 1.2 加入弹簧
header_layout.addStretch()
return header_layout
def init_form(self):
# 2.添加内容布局
form_layout = QHBoxLayout() # 创建添加内容布局
# 2.1 输入框
txt_asin = QLineEdit() # 新建一个输入框对象
txt_asin.setText("B07YN82X3B=100") # 设置默认的form数据
txt_asin.setPlaceholderText("请输入商品ID和价格,例如:B0818JJQQ8=88") # 设置灰色的提示信息
form_layout.addWidget(txt_asin) # 将输入框加入到布局中
# 2.2 添加按钮
btn_add = QPushButton("添加") # 新建一个添加按钮
form_layout.addWidget(btn_add) # 将添加按钮添加到form布局
return form_layout
def init_table(self):
# 3.表格数据展示布局
table_layout = QHBoxLayout()
# 3.1 创建表格
table_widget = QTableWidget(0, 8) # 新建一个0行8列的表格
# # 修改表格索引名
# item=QTableWidgetItem()
# item.setText("标题0")
# table_widget.setHorizontalHeaderItem(0,item)
# table_widget.setColumnWidth(0,150)#设置水平单元格0号位置的宽度 150
#
# item2=QTableWidgetItem()
# item2.setText("网址1")
# table_widget.setHorizontalHeaderItem(1,item2)
# table_widget.setColumnWidth(1,400)#设置水平单元格1号位置的宽度 400
#
# item3=QTableWidgetItem()
# item3.setText("行索引0")
# table_widget.setVerticalHeaderItem(0,item3)
table_header = [
{"field": "asin", "text": "ASIN", 'width': 120},
{"field": "title", "text": "标题", 'width': 150},
{"field": "url", "text": "URL", 'width': 400},
{"field": "price", "text": "底价", 'width': 100},
{"field": "success", "text": "成功次数", 'width': 100},
{"field": "error", "text": "503次数", 'width': 100},
{"field": "status", "text": "状态", 'width': 100},
{"field": "frequency", "text": "频率(N秒/次)", 'width': 100},
]
for idx, info in enumerate(table_header):
item = QTableWidgetItem()
item.setText(info['text'])
table_widget.setHorizontalHeaderItem(idx, item)
table_widget.setColumnWidth(idx, info['width'])
# 3.2 初始化表格数据
# 读取数据文件
import json
file_path = os.path.join(BASE_DIR, "db", "db.json")
with open(file_path, mode='r', encoding='utf-8') as f:
data = f.read()
data_list = json.loads(data)#读取得到了json数据
current_row_count = table_widget.rowCount() # 当前表格有多少行
for row_list in data_list:#每有一行json数据,我们就需要遍历一轮增加一行数据
table_widget.insertRow(current_row_count)#增加一行
# print(row_list) # ['B08166SLDF', 'AMD er', 'https://www.amazon.', 300.0, 0, 166, 1, 5]
# 把row_list写入这一行
for i, ele in enumerate(row_list):#enumerate中 i表示索引id,ele表示数据值
# 一个多目运算 如果i==6(此时是状态的数据) 如果STATUS_MAPPING中能够找到ele的索引,那么我们把ele设置成STATUS_MAPPING中的内容
ele = STATUS_MAPPING[ele] if i == 6 else ele
cell = QTableWidgetItem(str(ele))#注意我们的数据格式转为str,比如说状态的数据可能本身是int类型
if i in [0, 4, 5, 6]:
# 不可修改
cell.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)#指定索引单元格不能选中和修改
table_widget.setItem(current_row_count, i, cell)#写入数据到指定单元格
current_row_count += 1 #行数+1,这样下次遍历行时会在新的行下面新增一行
# 如果不新增行其实也可以用 current_row_count=table_widget.rowCount()替代
table_layout.addWidget(table_widget) # 把表格添加到表格布局中
return table_layout
def init_footer(self):
# 4.底部菜单
footer_layout = QHBoxLayout()
label_status = QLabel("未检测", self)
footer_layout.addWidget(label_status)
footer_layout.addStretch() # 添加弹簧,更加美观
btn_reset = QPushButton("重新初始化")
footer_layout.addWidget(btn_reset)
btn_recheck = QPushButton("重新检测")
footer_layout.addWidget(btn_recheck)
btn_reset_count = QPushButton("次数清零")
footer_layout.addWidget(btn_reset_count)
btn_delete = QPushButton("删除检测项")
footer_layout.addWidget(btn_delete)
btn_alert = QPushButton("SMTP报警配置")
footer_layout.addWidget(btn_alert)
btn_proxy = QPushButton("代理IP")
footer_layout.addWidget(btn_proxy)
return footer_layout
if __name__ == '__main__':
app = QApplication(sys.argv) # 实例化一个Application应用,所有的窗口均在其下运行
window = MainWindow() # 实例化窗口对象
window.show() # 窗口展示
sys.exit(app.exec_())
# app.exec_()运行主循环,并在退出时返回状态代码。
# sys.exit(n)退出您的应用程序并返回n到父进程(通常是您的shell)
总结
大家喜欢的话,给个👍,点个关注!给大家分享更多计算机专业学生的求学之路!
版权声明:
发现你走远了@mzh原创作品,转载必须标注原文链接
Copyright 2023 mzh
Crated:2023-3-1
欢迎关注 『pyqt5 从0基础开始项目实战』 专栏,持续更新中
欢迎关注 『pyqt5 从0基础开始项目实战』 专栏,持续更新中
『未完待续』