今天是实施想法的第二天,争取今天实现字词录入和复习的基本功能。当然接下来一定会遇到很多想不到的问题,我都会一一记录。
总目标

这个子页面的内容,我原本准备使用一个新的python模块,不在main.py下实现,目的是结构清晰,代码可读可维护。
但我在使用中发现,我的所有控件对象都在同一个ui下(如下图),将多个处理过程放到不同的py模块中,需要把ui做为全局变量,而全局的ui,不会判断该Ui下有哪些控件的,所以不会出现任何错误提示,反而给写脚本增加了极大的困难。
所以,用哪种方式让代码可读可维护,需要视情况而定。(实践才是硬道理呀!)

·
目标1:加载科目名称
用以下语句实现即可:
self.ui.cB_book_2.setModel(self.tableModelSub)
self.ui.cB_book_2.setModelColumn(self.tableModelSub.fieldIndex('sub_name'))
目标2:提交内容是字符时(完成信息提交和展示)
需要注意1:当条件满足时才可以提交,条件包括:
(1)如果不是图片,则“字词” 的录入框不能为空,记得去字符串两端的空格
(2)如果是图片,则图片的路径不能空
即用这样的脚本实现:
wordIn = self.ui.lineEdit_3.text().strip()
picIn = self.ui.label_22.text()
if self.ui.cB_grade_2.currentText() == '否' and wordIn != '':
print('不空且是字符')
# 下面是入库语句
# ....
elif self.ui.cB_grade_2.currentText() == '否' and picIn != '':
print('不空且是图片')
# 下面是入库语句
# ....
需要注意2:入库时需要明确是哪个学生哪个科目,而这两个信息在前台是以对应的name出现的,入库时却需要Id,因此需要通过一种方法,把所选学生或科目的ID找出来。
下面脚本,先找出下拉框当前选项的序号,再利用这个序号去tableModel中找出同一行的ID号:
sub_row = self.ui.cB_book_2.currentIndex()
sub_id = self.tableModelSub.data(self.tableModelSub.index(sub_row, 0))
stu_row = self.ui.cB_Stu.currentIndex()
stu_id = self.tableModelStu.data(self.tableModelStu.index(stu_row, 0))
2.1 字符串提交入库
方法一:
先查出数据库中当前tableMode的最后一行,然后以此行号为 word_id,并把相应参数填入。最后用setRecord()实现插入记录,记得submit。
lastRow = self.tableModelWord.rowCount()
print('最后一行是{}'.format(lastRow))
self.tableModelWord.insertRow(lastRow, QModelIndex())
curRec = self.tableModelWord.record() # 只有表头
curRec.setValue('word_id', 'w_' + str(lastRow))
curRec.setValue('pic_or_not', 'no')
curRec.setValue('word', wordIn)
curRec.setValue('means', means)
curRec.setValue('sub_id', sub_id)
curRec.setValue('stu_id', stu_id)
self.tableModelWord.setRecord(lastRow, curRec) # 插入记录
if self.tableModelWord.submitAll():
print('插入记录成功')
但该方法存在两个问题:
(1) tableModel 如果被设置了查询条件,对应的rowcount就不是全表的记录数;
(2) word表中如果出行删除行的操作,会使整个表的行数减少,也会导致rowcount重复。
以上两情形都会使word_id出现重复。
因此word_id 不应该依赖于rowcount。
方法二:
查询words表中的行数,如果为0,则word_id 从0开始;如果不为0,则使用max(word_id)+1。
调整以后又提交不成功了。
qr = QtSql.QSqlQuery(self.db)
qr.exec("select max(rowid) as myrowid from words")
qr.last()
if qr.value('myrowid') == '': # 新数据库会是这样的情况 没有一条记录
lastRow = 1
else:
qr.exec("select max(word_id) as max_id from words")
qr.last()
lastRow = qr.value('max_id') + 1
print('query查到的最后一条记录:{}'.format(lastRow))
qr.finish()
原因:
因为接下来的插入语句:
self.tableModelWord.insertRow(lastRow, QModelIndex())
中的lastRow是从0开始的,而上面的的lastRow是从1开始的。调整成一致,即可完成。
进一步优化功能
显然设计时没有考虑重复录入的问题,同一个单词应该避免重复录入。
qr_congfu = QtSql.QSqlQuery(self.db)
qr_congfu.exec("select word from words where word= '" + wordIn + "'")
qr_congfu.last()
if qr_congfu.value('word') == None: # 新数据库会是这样的情况 没有一条记录
dup = False
else:
dup = True
QMessageBox.warning(self, '提示:', '已经存在字词:'+str(wordIn))
qr_congfu.finish()
·
2.2 将已提交信息展现在前台视图控件中
在这里有一个问题需要先考虑清楚:视图控件中展示words表中所有的数据吗?还是只展示近几天的数据,还是只展示当天录入的数据?
这要看展示意义:
(1)确认提交成功了
(2)能看得出本次背单词的个数
对于历史数据,最好别展示。原因:
(1)随着时间推移,历史数据会越来越多,不便全展示;
(2)如果想了解一段时间内背诵的单词,可以单独增加个功能点。
想清楚这个问题,就好做功能设计了。
字词录入页的视图只展示当天该学生录入的字词,可以按科目分组展示。
写到这儿,我发现在表设计阶段少了一个时间字段😂
补上字段以后,还要补充一下python中关于时间的处理:
使用:
(1) QDate.currentDate(),可以得到当前日期
(2)QDate.currentDate().toString(‘yyyy-MM-dd’),可以将日期变成这样的格式“2022-11-05”
.
用以下脚本可以将需要的信息展示在视图中:
def qr_word_refresh(self):
self.qr_word = QtSql.QSqlQueryModel()
# qr_word = QtSql.QSqlQuery(self.db)
self.qr_word.setQuery("select a.word_id as '单词ID', a.picture as '图片', a.word as '字词', "
"a.means as '意思/易错点描述',b.sub_name as '科目' from words a, subject b"
" where a.sub_id = b.sub_id and input_day = '" + QDate.currentDate().toString('yyyy-MM-dd') + "' "
" order by b.sub_name,a.word_id desc" )
self.ui.tableView_4.setModel(self.qr_word)
self.ui.tableView_4.show()
errorTablecust = self.qr_word.lastError().text()
if errorTablecust != '': # 新数据库会是这样的情况 没有一条记录
QMessageBox.warning(self, '提示:', errorTablecust)
效果如下:
