(一)系统界面展示
(二)开发环境及功能说明
处理器:Apple M1 Max (内存:64G)
系统版本:MacOS Sonoma 14.1.2
开发环境:Anaconda(Python3.9) + Pycharm + PyQt5(5.15.10) + JSON
程序运行后弹出登录界面,登录成功后转跳系统操作界面,如登录失败给予弹窗提示;进入系统后通过对JSON数据文件操作,实现增删改查的功能;优化代码使用上下文菜单功能删除对应行。在本程序中我将新增,修改,查询共用三个输入框。减去了多线程,详细书写了登录功能。
(三)代码详解
本次程序将代码分为了三部分(两个.py文件,一个JSON文件),其中两个.py文件一个负责逻辑代码,一个负责页面,JSON文件存储数据。目录结构如下
SystemMain.py代码(页面)
这里我为了方便排版布局方便,使用了Qt Designer 进行布局上的设置,只是布局排版,没有使用槽的连接什么的(悄悄的讲:因为我不会用。。。)只是对主窗口进行布局,登录窗口直接写在了逻辑代码里面
注意:Qt Designer导出的是ui文件,因为没用Qt Designer完整制作只是排版布局,所以像按钮点击事件的连接还是要修改页面上的代码,所以这里要把后缀.ui的文件使用指令转换为.py的文件,方便我们修改点击事件和里面的标语。
ui文件转换为py文件的方法:在ui文件的目录下,使用:pyuic5 -o test.py test.ui
test.py 是转换后的文件名字,test.ui是需要转换的文件名字(这是pyqt5自带的转换工具)
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QAbstractItemView
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(535, 397)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.address_input = QtWidgets.QLineEdit(self.centralwidget)
self.address_input.setGeometry(QtCore.QRect(110, 40, 151, 31))
self.address_input.setPlaceholderText("请输入注册地址...") # 设置提示语
self.address_input.setObjectName("address_input")
self.username_input = QtWidgets.QLineEdit(self.centralwidget)
self.username_input.setPlaceholderText("请输入用户名...") # 设置提示语
self.username_input.setGeometry(QtCore.QRect(340, 40, 151, 31))
self.username_input.setObjectName("username_input")
self.password_input = QtWidgets.QLineEdit(self.centralwidget)
self.password_input.setPlaceholderText("请输入密码...") # 设置提示语
self.password_input.setGeometry(QtCore.QRect(340, 90, 151, 31))
self.password_input.setObjectName("password_input")
self.username_lab = QtWidgets.QLabel(self.centralwidget)
self.username_lab.setGeometry(QtCore.QRect(280, 50, 60, 16))
self.username_lab.setObjectName("username_lab")
self.password_lab = QtWidgets.QLabel(self.centralwidget)
self.password_lab.setGeometry(QtCore.QRect(290, 100, 60, 16))
self.password_lab.setObjectName("password_lab")
self.address_lab = QtWidgets.QLabel(self.centralwidget)
self.address_lab.setGeometry(QtCore.QRect(40, 50, 60, 16))
self.address_lab.setObjectName("address_lab")
self.select_btn = QtWidgets.QPushButton(self.centralwidget)
self.select_btn.setGeometry(QtCore.QRect(150, 90, 113, 32))
self.select_btn.setObjectName("select_btn")
self.select_btn.clicked.connect(self.submit_score)
self.insert_btn = QtWidgets.QPushButton(self.centralwidget)
self.insert_btn.setGeometry(QtCore.QRect(30, 90, 113, 32))
self.insert_btn.setObjectName("insert_btn")
self.insert_btn.clicked.connect(self.add_data)
self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
self.tableWidget.setGeometry(QtCore.QRect(40, 140, 451, 201))
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)
# self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
self.tableWidget.setColumnCount(0)
self.tableWidget.setRowCount(0)
self.result_lab = QtWidgets.QLabel(self.centralwidget)
self.result_lab.setGeometry(QtCore.QRect(40, 350, 451, 16))
self.result_lab.setObjectName("result_lab")
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
self.logout_btn = QtWidgets.QPushButton(self.centralwidget)
self.logout_btn.setGeometry(QtCore.QRect(440, 340, 90, 32))
self.logout_btn.setObjectName("logout_btn")
self.logout_btn.clicked.connect(self.logout)
self.save_btn = QtWidgets.QPushButton(self.centralwidget)
self.save_btn.setGeometry(QtCore.QRect(360, 340, 90, 32))
self.save_btn.setObjectName("save_btn")
self.save_btn.clicked.connect(self.updata)
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.username_lab.setText(_translate("MainWindow", "用户名:"))
self.password_lab.setText(_translate("MainWindow", "密码:"))
self.address_lab.setText(_translate("MainWindow", "注册地址:"))
self.select_btn.setText(_translate("MainWindow", "用户查询"))
self.insert_btn.setText(_translate("MainWindow", "用户添加"))
self.result_lab.setText(_translate("MainWindow", "用户提示区"))
self.logout_btn.setText(_translate("MainWindow", "登出"))
self.save_btn.setText(_translate("MainWindow", "保存"))
SystemLogic.py代码(逻辑):
导入需要使用的模块
import json
import sys
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtGui import QContextMenuEvent
from PyQt5.QtWidgets import QMainWindow, QApplication, QTableWidgetItem, QMenu, QAction, QMessageBox, QDialog, \
QLineEdit, QLabel, QPushButton, QVBoxLayout
from SystemMain import Ui_MainWindow
登录功能:
class LoginAndDisplay(QDialog):
login_successful = pyqtSignal()
def __init__(self, parent=None):
super(LoginAndDisplay, self).__init__(parent)
self.logged_in = False
self.user_username = "admin" # 设置用户账号
self.user_password = "admin" # 设置用户密码
self.setWindowTitle('超级管理员登录')
self.setFixedSize(300, 150)
self.label_username = QLabel('账号:', self)
self.input_username = QLineEdit(self)
self.label_password = QLabel('密码:', self)
self.input_password = QLineEdit(self)
self.input_password.setEchoMode(QLineEdit.Password)
self.btn_login = QPushButton('登录', self)
self.btn_login.clicked.connect(self.login)
# -------账号密码免输入--------
self.input_username.setText(self.user_username)
self.input_password.setText(self.user_password)
layout = QVBoxLayout(self)
layout.addWidget(self.label_username)
layout.addWidget(self.input_username)
layout.addWidget(self.label_password)
layout.addWidget(self.input_password)
layout.addWidget(self.btn_login)
# ------------登录功能-------------
def login(self):
username_input = self.input_username.text()
password_input = self.input_password.text()
if username_input == self.user_username and password_input == self.user_password:
self.logged_in = True
self.login_successful.emit() # 发出登录成功的信号
else:
QMessageBox.warning(self, "登录失败", "账号或密码错误!", QMessageBox.Ok)
-
login_successful = pyqtSignal()
: 这是一个 PyQt5 的信号,用于发出登录成功的信号。在后面的代码中,通过连接这个信号和相应的槽函数来实现在登录成功时的一些操作。 -
__init__(self, parent=None)
: 类的构造函数,初始化登录界面的各个组件。 -
login(self)
: 登录功能的实现方法。在用户点击登录按钮时触发,获取用户输入的用户名和密码,与预设的账号密码进行比对。如果匹配成功,则设置self.logged_in
为True
,并发出login_successful
信号,表示登录成功。如果匹配失败,则弹出一个警告框提示用户账号或密码错误。 -
默认账号和密码:
-
self.user_username = "admin"
设置默认的用户名为 "admin"。self.user_password = "admin"
设置默认的密码为 "admin"。 -
设置输入框内的初始值:(免去了测试时输入账号密码)
self.input_username.setText(self.user_username)
: 将用户名输入框的文本设置为默认的用户名。self.input_password.setText(self.user_password)
: 将密码输入框的文本设置为默认的密码。
退出功能:
# 用户退出登录
def logout(self):
self.close()
login_and_display.show()
-
self.close()
关闭当前的UserDisplay
窗口。这个方法用于关闭当前活动的窗口或对话框。 -
login_and_display.show()
显示登录界面。login_and_display
是一个LoginAndDisplay
类的实例,通过这个语句,用户退出登录后会返回到登录界面。
读取写入JSON
# 读取原有数据
with open('data.json', 'r') as file:
existing_data = json.load(file)
-
with open('data.json', 'r') as file:
打开文件 'data.json',并使用with
语句,确保在读取完数据后正确关闭文件。'r'
参数表示以只读模式打开文件。 -
existing_data = json.load(file)
使用 Python 的json
模块中的load
函数,将打开的文件对象file
中的 JSON 数据加载到existing_data
变量中。这样,'data.json' 文件中的原有数据就被读取到一个 Python 数据结构中。
# 将更新后的数据写回文件
with open('data.json', 'w') as file:
json.dump(existing_data, file, indent=2)
-
json.dump(existing_data, file, indent=2)
使用 Python 的json
模块中的dump
函数,将existing_data
中的数据写入到文件对象file
中。参数indent=2
是为了让写入的 JSON 数据更加可读。这一步实际上是将原有的数据覆盖掉,用更新后的数据进行替换。
查询数据:
# 查询所有数据
def load_data(self):
try:
# 读取原有数据
with open('data.json', 'r') as file:
existing_data = json.load(file)
# 清空表格
self.tableWidget.setRowCount(0)
if len(existing_data) == 0:
self.tableWidget.setRowCount(0)
else:
self.tableWidget.setRowCount(len(existing_data))
self.tableWidget.setColumnCount(3)
for row, data in enumerate(existing_data):
self.tableWidget.setItem(row, 0, QTableWidgetItem(data.get('address')))
self.tableWidget.setItem(row, 1, QTableWidgetItem(data.get('username')))
self.tableWidget.setItem(row, 2, QTableWidgetItem(data.get('password')))
# 设置列宽
self.tableWidget.setColumnWidth(0, 150)
self.tableWidget.setColumnWidth(1, 140)
self.tableWidget.setColumnWidth(2, 130)
# 设置表头标签
self.tableWidget.setHorizontalHeaderLabels(['address', 'username', 'password'])
except FileNotFoundError:
print("File 'data.json' not found.")
self.result_lab.setText("出错啦!")
except Exception as e:
self.result_lab.setText("出错啦!")
print('Error loading data:', e)
print('Error loading data:', repr(e))
-
(1)with open('data.json', 'r') as file:
使用with
语句打开 'data.json' 文件,以只读模式读取文件。 -
(2)existing_data = json.load(file)
使用json.load
方法将 'data.json' 文件中的 JSON 数据加载到existing_data
变量中。 -
(3)self.tableWidget.setRowCount(0)
清空表格的行数,以确保在加载新数据之前表格是空的。 -
(4)if len(existing_data) == 0:
检查是否存在数据。如果没有数据,表格行数仍然为0。 -
(5)self.tableWidget.setRowCount(len(existing_data))
设置表格的行数为existing_data
中的数据项数目。 -
(6)self.tableWidget.setColumnCount(3)
设置表格的列数为3,对应 'address', 'username', 'password'。 -
(7)使用循环遍历
existing_data
中的每一项,并将其填充到表格的相应位置,使用QTableWidgetItem
。 -
(8)self.tableWidget.setHorizontalHeaderLabels(['address', 'username', 'password'])
设置表头标签。 -
(9)except FileNotFoundError:
捕获文件未找到的异常,并打印错误消息。except Exception as e:
捕获其他可能的异常,并打印错误消息。
删除功能:
def contextMenuEvent(self, event: QContextMenuEvent):
# 创建上下文菜单
context_menu = QMenu(self)
# 检查表格中是否有选中的项
selected_items = self.tableWidget.selectedItems()
if selected_items:
# 向上下文菜单添加“删除”动作
delete_action = QAction("删除本行", self)
delete_action.triggered.connect(self.delete_selected_rows)
context_menu.addAction(delete_action)
# 在事件的位置显示上下文菜单
context_menu.exec_(event.globalPos())
def delete_selected_rows(self):
# 获取选中的行并删除它们
selected_rows = set()
for item in self.tableWidget.selectedItems():
selected_rows.add(item.row())
# 以逆序的方式排序行,以避免删除时的索引问题
for row in sorted(selected_rows, reverse=True):
self.tableWidget.removeRow(row)
# 保存更新后的数据到 JSON 文件
# 从表格获取数据
table_data = []
for row in range(self.tableWidget.rowCount()):
row_data = {
'address': self.tableWidget.item(row, 0).text(),
'username': self.tableWidget.item(row, 1).text(),
'password': self.tableWidget.item(row, 2).text(),
}
table_data.append(row_data)
# 将数据保存到 JSON 文件
with open('data.json', 'w', encoding='utf-8') as file:
json.dump(table_data, file, ensure_ascii=False, indent=2)
self.result_lab.setText(f"Delect Successful... ")
-
contextMenuEvent
方法:- 当右键点击表格时触发,创建一个上下文菜单(
QMenu
)。 - 通过检查表格是否有选中的项,决定是否在上下文菜单中添加 "删除本行" 的动作。
- 通过
context_menu.exec_(event.globalPos())
在事件的位置显示上下文菜单。
- 当右键点击表格时触发,创建一个上下文菜单(
-
delete_selected_rows
方法:- 获取选中的行号,并以逆序方式排序,以避免删除时的索引问题。
- 使用
self.tableWidget.removeRow(row)
删除选中的行。
-
保存更新后的数据到 JSON 文件:
- 创建一个列表
table_data
,用于存储更新后的数据。 - 通过遍历表格的每一行,获取每行的数据,添加到
table_data
中。 - 使用
json.dump
将table_data
写入 'data.json' 文件。 - 在界面上更新
self.result_lab
标签,显示删除成功的消息。
- 创建一个列表
新增功能:
def add_data(self):
# 获取输入框中的数据
address_ = self.address_input.text()
username_ = self.username_input.text()
password_ = self.password_input.text()
new_data = {'address': address_, 'username': username_, 'password': password_}
# 进行输入校验
if all(value != '' for value in [address_, username_, password_]):
# 读取原有数据
with open('data.json', 'r') as file:
existing_data = json.load(file)
# 添加新数据
existing_data.append(new_data)
# 将更新后的数据写回文件
with open('data.json', 'w') as file:
json.dump(existing_data, file, indent=2)
self.result_lab.setText(f'New Data Address: {address_}')
# 清空输入框
self.address_input.clear()
self.username_input.clear()
self.password_input.clear()
# 重新加载数据
self.load_data()
else:
# 提示用户输入不完整
QMessageBox.warning(self, '警告', '请填写完整的数据', QMessageBox.Ok)
-
获取输入框中的数据:
通过self.address_input.text()
,self.username_input.text()
,self.password_input.text()
获取用户在界面输入框中输入的地址、用户名和密码。 -
进行输入校验:
使用if all(value != '' for value in [address_, username_, password_]):
进行输入校验,确保地址、用户名和密码都不为空。 -
读取原有数据:
使用with open('data.json', 'r') as file:
读取原有的 JSON 数据。 -
添加新数据:
- 创建一个字典
new_data
包含新的地址、用户名和密码。 - 将新数据添加到原有数据的列表
existing_data
中。
- 创建一个字典
-
将更新后的数据写回文件:
- 使用
with open('data.json', 'w') as file:
将更新后的数据写回 'data.json' 文件中。 - 在界面上更新
self.result_lab
标签,显示添加成功的消息。
- 使用
-
清空输入框:
使用self.address_input.clear()
,self.username_input.clear()
,self.password_input.clear()
清空输入框,以便用户输入下一组数据。 -
重新加载数据:
使用self.load_data()
方法重新加载数据,以在表格中显示最新的数据。 -
输入不完整的提示:
如果用户未填写完整数据,使用QMessageBox.warning
显示一个警告框,提示用户需要填写完整数据。
查询功能:
def submit_score(self):
try:
search_address = self.address_input.text()
if search_address != '':
# 读取原有数据
with open('data.json', 'r') as file:
existing_data = json.load(file)
# 查找具有相应注册地址的数据
search_result = [data for data in existing_data if data.get('address') == search_address]
if not search_result: # 如果 search_result 为空
self.result_lab.setText("请输入注册地址进行查询...")
return
self.tableWidget.setRowCount(len(search_result))
for row, data in enumerate(search_result):
self.tableWidget.setItem(row, 0, QTableWidgetItem(data.get('address')))
self.tableWidget.setItem(row, 1, QTableWidgetItem(data.get('username')))
self.tableWidget.setItem(row, 2, QTableWidgetItem(data.get('password')))
else:
self.result_lab.setText("暂无查询结果(返回数据总页)")
self.load_data()
except FileNotFoundError:
self.result_lab.setText("文件未找到")
except Exception as e:
print(e)
self.result_lab.setText("出错啦:" + str(e))
finally:
self.address_input.clear()
-
获取搜索地址:
通过self.address_input.text()
获取用户在界面输入框中输入的注册地址。 -
进行查询:
如果输入的搜索地址不为空,执行以下操作:- 使用列表推导式查找具有相应注册地址的数据,保存在
search_result
中。 - 使用
with open('data.json', 'r') as file:
读取原有的 JSON 数据。
- 使用列表推导式查找具有相应注册地址的数据,保存在
-
处理查询结果:
- 如果
search_result
不为空,设置表格的行数,并将查询结果填充到表格中。 - 如果
search_result
为空,设置界面上的self.result_lab
标签,显示相应的提示信息。
- 如果
-
处理未输入搜索地址的情况:
- 如果输入的搜索地址为空,设置界面上的
self.result_lab
标签,显示相应的提示信息。 - 调用
self.load_data()
方法,重新加载所有数据以显示在表格中。
- 如果输入的搜索地址为空,设置界面上的
-
异常处理:
捕获可能发生的异常,如文件未找到或其他异常,并在界面上显示相应的错误消息。 -
清空输入框:
使用self.address_input.clear()
清空输入框,以便用户输入下一组数据。
更新功能:
def updata(self):
# 获取输入框中的数据
address_ = self.address_input.text()
username_ = self.username_input.text()
password_ = self.password_input.text()
# 读取原有数据
with open('data.json', 'r', encoding='utf-8') as file:
existing_data = json.load(file)
# 根据地址修改数据
for item in existing_data:
if item['address'] == address_:
item['username'] = username_
item['password'] = password_
# 将更新后的数据保存回 JSON 文件
with open('data.json', 'w', encoding='utf-8') as file:
json.dump(existing_data, file, ensure_ascii=False, indent=2)
self.result_lab.setText("数据已更新")
self.load_data()
-
获取输入框中的数据:
通过self.address_input.text()
,self.username_input.text()
,self.password_input.text()
获取用户在界面输入框中输入的地址、用户名和密码。 -
读取原有数据:
使用with open('data.json', 'r', encoding='utf-8') as file:
读取原有的 JSON 数据。 -
根据地址修改数据:
遍历existing_data
中的每个字典,如果找到匹配的地址,更新该地址对应的用户名和密码。 -
将更新后的数据保存回 JSON 文件:
- 使用
with open('data.json', 'w', encoding='utf-8') as file:
将更新后的数据写回 'data.json' 文件中。 - 在界面上更新
self.result_lab
标签,显示数据已更新的提示信息。
- 使用
-
重新加载数据:
使用self.load_data()
方法重新加载数据,以在表格中显示最新的数据。
运行:
if __name__ == '__main__':
app = QApplication(sys.argv)
login_and_display = LoginAndDisplay()
main_window = MainWindow()
def show_user_display():
login_and_display.close()
main_window.show()
main_window.result_lab.setText("Login System Success...")
login_and_display.login_successful.connect(show_user_display)
login_and_display.exec_()
sys.exit(app.exec_())
-
创建 QApplication 对象:
app = QApplication(sys.argv)
创建了一个 Qt 应用程序对象。 -
创建 LoginAndDisplay 和 MainWindow 对象:
login_and_display = LoginAndDisplay()
创建了登录窗口对象。main_window = MainWindow()
创建了主窗口对象。
-
定义 show_user_display 函数:
这个函数将在登录成功时被调用,关闭登录窗口,显示主窗口,并在主窗口的result_lab
标签中显示登录成功的提示信息。 -
连接信号和槽:
login_and_display.login_successful.connect(show_user_display)
将登录窗口的登录成功信号连接到show_user_display
函数。 -
显示登录窗口:
login_and_display.exec_()
显示登录窗口并启动应用程序的事件循环。 -
退出应用程序:
sys.exit(app.exec_())
在事件循环结束后,通过sys.exit
退出应用程序。
(四)完整代码
SystemLogic(逻辑代码)
import json
import sys
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtGui import QContextMenuEvent
from PyQt5.QtWidgets import QMainWindow, QApplication, QTableWidgetItem, QMenu, QAction, QMessageBox, QDialog, \
QLineEdit, QLabel, QPushButton, QVBoxLayout
from SystemMain import Ui_MainWindow
class LoginAndDisplay(QDialog):
login_successful = pyqtSignal()
def __init__(self, parent=None):
super(LoginAndDisplay, self).__init__(parent)
self.logged_in = False
self.user_username = "admin" # 设置用户账号
self.user_password = "admin" # 设置用户密码
self.setWindowTitle('超级管理员登录')
self.setFixedSize(300, 150)
self.label_username = QLabel('账号:', self)
self.input_username = QLineEdit(self)
self.label_password = QLabel('密码:', self)
self.input_password = QLineEdit(self)
self.input_password.setEchoMode(QLineEdit.Password)
self.btn_login = QPushButton('登录', self)
self.btn_login.clicked.connect(self.login)
# -------账号密码免输入--------
self.input_username.setText(self.user_username)
self.input_password.setText(self.user_password)
layout = QVBoxLayout(self)
layout.addWidget(self.label_username)
layout.addWidget(self.input_username)
layout.addWidget(self.label_password)
layout.addWidget(self.input_password)
layout.addWidget(self.btn_login)
# ------------登录功能-------------
def login(self):
username_input = self.input_username.text()
password_input = self.input_password.text()
if username_input == self.user_username and password_input == self.user_password:
self.logged_in = True
self.login_successful.emit() # 发出登录成功的信号
else:
QMessageBox.warning(self, "登录失败", "账号或密码错误!", QMessageBox.Ok)
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setupUi(self)
self.load_data()
# 用户退出登录
def logout(self):
self.close()
login_and_display.show()
# 查询所有数据
def load_data(self):
try:
# 读取原有数据
with open('data.json', 'r') as file:
existing_data = json.load(file)
# 清空表格
self.tableWidget.setRowCount(0)
if len(existing_data) == 0:
self.tableWidget.setRowCount(0)
else:
self.tableWidget.setRowCount(len(existing_data))
self.tableWidget.setColumnCount(3)
for row, data in enumerate(existing_data):
self.tableWidget.setItem(row, 0, QTableWidgetItem(data.get('address')))
self.tableWidget.setItem(row, 1, QTableWidgetItem(data.get('username')))
self.tableWidget.setItem(row, 2, QTableWidgetItem(data.get('password')))
# 设置列宽
self.tableWidget.setColumnWidth(0, 150)
self.tableWidget.setColumnWidth(1, 140)
self.tableWidget.setColumnWidth(2, 130)
# 设置表头标签
self.tableWidget.setHorizontalHeaderLabels(['address', 'username', 'password'])
except FileNotFoundError:
print("File 'data.json' not found.")
self.result_lab.setText("出错啦!")
except Exception as e:
self.result_lab.setText("出错啦!")
print('Error loading data:', e)
print('Error loading data:', repr(e))
def contextMenuEvent(self, event: QContextMenuEvent):
# 创建上下文菜单
context_menu = QMenu(self)
# 检查表格中是否有选中的项
selected_items = self.tableWidget.selectedItems()
if selected_items:
# 向上下文菜单添加“删除”动作
delete_action = QAction("删除本行", self)
delete_action.triggered.connect(self.delete_selected_rows)
context_menu.addAction(delete_action)
# 在事件的位置显示上下文菜单
context_menu.exec_(event.globalPos())
def delete_selected_rows(self):
# 获取选中的行并删除它们
selected_rows = set()
for item in self.tableWidget.selectedItems():
selected_rows.add(item.row())
# 以逆序的方式排序行,以避免删除时的索引问题
for row in sorted(selected_rows, reverse=True):
self.tableWidget.removeRow(row)
# 保存更新后的数据到 JSON 文件
# 从表格获取数据
table_data = []
for row in range(self.tableWidget.rowCount()):
row_data = {
'address': self.tableWidget.item(row, 0).text(),
'username': self.tableWidget.item(row, 1).text(),
'password': self.tableWidget.item(row, 2).text(),
}
table_data.append(row_data)
# 将数据保存到 JSON 文件
with open('data.json', 'w', encoding='utf-8') as file:
json.dump(table_data, file, ensure_ascii=False, indent=2)
self.result_lab.setText(f"Delect Successful... ")
def add_data(self):
# 获取输入框中的数据
address_ = self.address_input.text()
username_ = self.username_input.text()
password_ = self.password_input.text()
new_data = {'address': address_, 'username': username_, 'password': password_}
# 进行输入校验
if all(value != '' for value in [address_, username_, password_]):
# 读取原有数据
with open('data.json', 'r') as file:
existing_data = json.load(file)
# 添加新数据
existing_data.append(new_data)
# 将更新后的数据写回文件
with open('data.json', 'w') as file:
json.dump(existing_data, file, indent=2)
self.result_lab.setText(f'New Data Address: {address_}')
# 清空输入框
self.address_input.clear()
self.username_input.clear()
self.password_input.clear()
# 重新加载数据
self.load_data()
else:
# 提示用户输入不完整
QMessageBox.warning(self, '警告', '请填写完整的数据', QMessageBox.Ok)
# ...
def submit_score(self):
try:
search_address = self.address_input.text()
if search_address != '':
# 读取原有数据
with open('data.json', 'r') as file:
existing_data = json.load(file)
# 查找具有相应注册地址的数据
search_result = [data for data in existing_data if data.get('address') == search_address]
if not search_result: # 如果 search_result 为空
self.result_lab.setText("请输入注册地址进行查询...")
return
self.tableWidget.setRowCount(len(search_result))
for row, data in enumerate(search_result):
self.tableWidget.setItem(row, 0, QTableWidgetItem(data.get('address')))
self.tableWidget.setItem(row, 1, QTableWidgetItem(data.get('username')))
self.tableWidget.setItem(row, 2, QTableWidgetItem(data.get('password')))
else:
self.result_lab.setText("暂无查询结果(返回数据总页)")
self.load_data()
except FileNotFoundError:
self.result_lab.setText("文件未找到")
except Exception as e:
print(e)
self.result_lab.setText("出错啦:" + str(e))
finally:
self.address_input.clear()
def updata(self):
# 获取输入框中的数据
address_ = self.address_input.text()
username_ = self.username_input.text()
password_ = self.password_input.text()
# 读取原有数据
with open('data.json', 'r', encoding='utf-8') as file:
existing_data = json.load(file)
# 根据地址修改数据
for item in existing_data:
if item['address'] == address_:
item['username'] = username_
item['password'] = password_
# 将更新后的数据保存回 JSON 文件
with open('data.json', 'w', encoding='utf-8') as file:
json.dump(existing_data, file, ensure_ascii=False, indent=2)
self.result_lab.setText("数据已更新")
self.load_data()
if __name__ == '__main__':
app = QApplication(sys.argv)
login_and_display = LoginAndDisplay()
main_window = MainWindow()
def show_user_display():
login_and_display.close()
main_window.show()
main_window.result_lab.setText("Login System Success...")
login_and_display.login_successful.connect(show_user_display)
login_and_display.exec_()
sys.exit(app.exec_())
SystemMain(页面代码)
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QAbstractItemView
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(535, 397)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.address_input = QtWidgets.QLineEdit(self.centralwidget)
self.address_input.setGeometry(QtCore.QRect(110, 40, 151, 31))
self.address_input.setPlaceholderText("请输入注册地址...") # 设置提示语
self.address_input.setObjectName("address_input")
self.username_input = QtWidgets.QLineEdit(self.centralwidget)
self.username_input.setPlaceholderText("请输入用户名...") # 设置提示语
self.username_input.setGeometry(QtCore.QRect(340, 40, 151, 31))
self.username_input.setObjectName("username_input")
self.password_input = QtWidgets.QLineEdit(self.centralwidget)
self.password_input.setPlaceholderText("请输入密码...") # 设置提示语
self.password_input.setGeometry(QtCore.QRect(340, 90, 151, 31))
self.password_input.setObjectName("password_input")
self.username_lab = QtWidgets.QLabel(self.centralwidget)
self.username_lab.setGeometry(QtCore.QRect(280, 50, 60, 16))
self.username_lab.setObjectName("username_lab")
self.password_lab = QtWidgets.QLabel(self.centralwidget)
self.password_lab.setGeometry(QtCore.QRect(290, 100, 60, 16))
self.password_lab.setObjectName("password_lab")
self.address_lab = QtWidgets.QLabel(self.centralwidget)
self.address_lab.setGeometry(QtCore.QRect(40, 50, 60, 16))
self.address_lab.setObjectName("address_lab")
self.select_btn = QtWidgets.QPushButton(self.centralwidget)
self.select_btn.setGeometry(QtCore.QRect(150, 90, 113, 32))
self.select_btn.setObjectName("select_btn")
self.select_btn.clicked.connect(self.submit_score)
self.insert_btn = QtWidgets.QPushButton(self.centralwidget)
self.insert_btn.setGeometry(QtCore.QRect(30, 90, 113, 32))
self.insert_btn.setObjectName("insert_btn")
self.insert_btn.clicked.connect(self.add_data)
self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
self.tableWidget.setGeometry(QtCore.QRect(40, 140, 451, 201))
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)
# self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
self.tableWidget.setColumnCount(0)
self.tableWidget.setRowCount(0)
self.result_lab = QtWidgets.QLabel(self.centralwidget)
self.result_lab.setGeometry(QtCore.QRect(40, 350, 451, 16))
self.result_lab.setObjectName("result_lab")
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
self.logout_btn = QtWidgets.QPushButton(self.centralwidget)
self.logout_btn.setGeometry(QtCore.QRect(440, 340, 90, 32))
self.logout_btn.setObjectName("logout_btn")
self.logout_btn.clicked.connect(self.logout)
self.save_btn = QtWidgets.QPushButton(self.centralwidget)
self.save_btn.setGeometry(QtCore.QRect(360, 340, 90, 32))
self.save_btn.setObjectName("save_btn")
self.save_btn.clicked.connect(self.updata)
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.username_lab.setText(_translate("MainWindow", "用户名:"))
self.password_lab.setText(_translate("MainWindow", "密码:"))
self.address_lab.setText(_translate("MainWindow", "注册地址:"))
self.select_btn.setText(_translate("MainWindow", "用户查询"))
self.insert_btn.setText(_translate("MainWindow", "用户添加"))
self.result_lab.setText(_translate("MainWindow", "用户提示区"))
self.logout_btn.setText(_translate("MainWindow", "登出"))
self.save_btn.setText(_translate("MainWindow", "保存"))
JSON文件数据
[
{
"address": "rdi@pf.io",
"username": "\u79b9\u5b97",
"password": "pwd446"
},
{
"address": "r2ulhht8@hrtnfsic.io",
"username": "\u6a0a\u5b50",
"password": "pwd304"
},
{
"address": "evhqx@orv.io",
"username": "\u6743\u677e\u5357",
"password": "pwd176"
},
{
"address": "qtq4qybp4j@swtfdk.im",
"username": "\u59ec\u8fdc",
"password": "pwd340"
},
{
"address": "oiax41g6j@n4mi.im",
"username": "\u8a00\u671d",
"password": "pwd030"
},
{
"address": "vslp7@vc.me",
"username": "\u53f2\u987a",
"password": "pwd983"
},
{
"address": "yf8ydn@hfdcq.im",
"username": "\u51b7\u5a23\u806a",
"password": "pwd501"
},
{
"address": "5dj3qrym6@g3.cn",
"username": "\u9ea6\u632f",
"password": "pwd512"
},
{
"address": "f2w3i0@dn2.cc",
"username": "\u5b8b\u671d",
"password": "pwd311"
},
{
"address": "12333",
"username": "12333",
"password": "24234"
}
]
本期的PyQt的程序案例就分享到这了!关注+收藏!关注专栏后期会更新更多PyQt的程序!感谢支持!(平均1-3天更新!)