录入数据修改
一个好用的应用程序,一定是在千百遍的测试中逐渐完善起来的。我和孩子们在使用自己开发的“按记忆曲线识记知识点”应用程序时,发现无法修改录入错误的数据。哈哈~ 虽然一直都知道“增删改查”这个概念,但真正做软件时却给忽略了。那么,开始修改吧!
一、设计思路
1、修改操作可能发生在录入过程中,也可能发生在背记过程中。所以两个页面都应该有修改功能;
2、修改的方式,希望是双击某单条记录,弹出一个修改窗口,然后提交更新原记录。看上去不难,但需要增加一个小弹窗。
二、解决过程
2.1 设计修改窗口
简单设计了一个数据修改的页面:
2.2 转成py文件
使用以下语句,将ui文件转换为py文件:
pyuic5 -o ui_correct.py program\ui\correct.ui
2.3 写业务逻辑
1、先显示一下基础页面
以下程序可以先显示一下基础页面:
import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, QDialog)
from ui_correct import Ui_correction
class QmyCorrection(QDialog):
def __init__(self, parent=None):
super().__init__(parent) # 调用父类构造函数,创建窗体
self.ui = Ui_correction() # 创建UI对象
self.ui.setupUi(self) # 构造UI界面
# ============窗体测试程序 ==================
if __name__ == "__main__": # 用于当前窗体测试
app = QApplication(sys.argv) # 创建GUI应用程序
form = QmyCorrection() # 创建窗体
form.show()
sys.exit(app.exec_())
运行该页面后,发现窗体相对我的机器来说屏幕有点小。
2、配合适配器,自动调整窗口大小
可以增加以下语句,让窗口自动调整大小:
# 调整窗口大小
desktop = QDesktopWidget()
self.screen_width = desktop.screenGeometry().width()
self.screen_height = desktop.screenGeometry().height()
self.resize(self.screen_width/3,self.screen_height/3)
3、在数据录入窗口或背记窗口双击某条记录
3.1 增加信号
分别给数据录入窗口和背记窗口增加以下内容,以便双击时打开数据修改页面:
self.ui.tableView_4.doubleClicked.connect(self.correctWords)
self.ui.tableView.doubleClicked.connect(self.correctWords)
3.2 在槽函数中打开修改页面
下面脚本可以实现双击打开修改页面
# 双击打开修改页面
self.page_correct = myCorrect.QmyCorrection()
self.page_correct.setAttribute(Qt.WA_DeleteOnClose) # 关闭时自动删除这个实例
self.page_correct.exec()
但是新页面怎样知道需要修改哪一条记录呢?
【技术点关联】前面的笔记中有一篇
“复习页面逻辑实现”时,好像也有过这样的思考。见: https://blog.csdn.net/zwy_0309/article/details/127714340
其中问题“选择单词进入复习计划列表”提到:
self.ui.tableView.selectionModel().selectedRows(),可以得到一个index列表,这些index有一个row()属性,可以帮助我们获取选中的行号。
self.qrModel.record(行号).value(列号),可以得到某个字段信息。
但这次不同于上次选择复习单词,上次选择了多行,这次没有选择,只是在某一行上双击了一下,有没有其他办法呢?正面语句可以解决问题
【答案】tableview.selectedIndexes()[0].row()
3.3 两个页面之间传递信号
之前我采用了全局变量法解决两个页面之间传递参数的问题,此外还有两种方法:
❣️一种常见方法,就是使用信号槽的方法,适用于子窗口向主窗口传递信号
【个人总结】
💭 定义信号:在发射信号侧,且在init之前;使用pyqtSignal(type);
💭 绑定信号:在接收信号侧,用connect 把信号和槽绑定在一起
💭 发射信号:在发射信号侧,用emit 发射信号
❣️ 我认为还有一种方法:适用于主窗口中向子窗口传递参数
即,在主窗口中打开子窗口对象,并在主窗口中调用子窗口对象中的方法crt,而crt方法带着一个参数,即word_id。
3.4 在子窗口中显示原数据,并在修改提交后,更新数据
def crt(self, canshu):
print('我在子窗中,我得到的参数是{}。'.format(canshu))
self.word_id = canshu
# 显示原数据
self.stuModel = myGlobValues.get_value('G_tableModelStu')
self.subModel = myGlobValues.get_value('G_tableModelSub')
self.G_db = myGlobValues.get_value('G_db')
self.qr_word = QSqlQuery(self.G_db)
self.qr_word.exec("select a.word_id , a.word , a.means ,c.stu_name ,b.sub_name"
" from words a, subject b, student c "
" where a.sub_id = b.sub_id and a.stu_id=c.stu_id and a.word_id = '" + self.word_id +"'" )
self.qr_word.last()
word = self.qr_word.value(1)
means = self.qr_word.value(2)
stu_name = self.qr_word.value(3)
sub_name = self.qr_word.value(4)
self.ui.textEdit.setText(word)
self.ui.textEdit_2.setText(means)
self.ui.comboBox.setModel(self.stuModel)
self.ui.comboBox.setModelColumn(self.stuModel.fieldIndex('stu_name'))
row = 0
for i in range(0,self.stuModel.rowCount()):
if self.stuModel.record(i).value(1) == stu_name:
row = i
print(row)
self.ui.comboBox.setCurrentIndex(row)
self.ui.comboBox_2.setModel(self.subModel)
self.ui.comboBox_2.setModelColumn(self.subModel.fieldIndex('sub_name'))
row_sub = 0
for i in range(0, self.subModel.rowCount()):
if self.subModel.record(i).value(1) == sub_name:
row_sub = i
self.ui.comboBox_2.setCurrentIndex(row_sub)
def do_commit(self):
stu_row = self.ui.comboBox.currentIndex()
stu_id = self.stuModel.data(self.stuModel.index(stu_row, 0))
sub_row = self.ui.comboBox_2.currentIndex()
sub_id = self.subModel.data(self.subModel.index(sub_row, 0))
word = self.ui.textEdit.toPlainText()
means = self.ui.textEdit_2.toPlainText()
self.qr_word.exec("update words set word = '"+word+"',"
" means = '"+ means +"',"
" stu_id = '"+stu_id+"',"
" sub_id= '"+sub_id+"'"
" where word_id = '"+self.word_id+"'")
errorTable = self.qr_word.lastError().text()
if errorTable != '': # 新数据库会是这样的情况 没有一条记录
QMessageBox.warning(self, '提示:', errorTable)
else:
cs = True
self.s_correct.emit(cs)