QLineEdit拾遗:数据的过滤、验证和补全 (3)

如此一来我们既验证了数据的合法性又处理了所有可能的输入情况。当然,通常我更建议你使用现有的QDoubleValidator和QRegExpValidator等现有的验证器,或将它们组合使用,这样更简单也更不容易出错。

自动补全——QCompleter

我们已经讲解了输入的过滤和验证,最后该讲讲补全了。

可以说过滤和验证是比较常用的功能的话,那补全就没有那么常见了。或者说,通常我们不需要关心它,比如QComboBox自带了QCompleter,它工作得也很好,所以我们往往忽略了它的存在。当然不只是下拉框,在QLineEdit中我们也可以用它和它的派生类实现补全效果。

功能:QCompleter包含了一个叫completeModel的数据模型,里面包含了用于根据输入信息进行补全的所有数据,通常是个listModel,也可以是设置了补全所用数据位于哪一列的tableModel,当然你还可以用treeModel,不过这超过了我们的讨论范围。

显示效果:completer从你输入的第一个字符开始匹配,如果在completeModel中找到了以输入内容开头的信息则会在edit下把所有匹配项一次放入一个下拉框并显示,你也可以设置为将第一个匹配项的数据替换放入edit。

还有一点我想额外补充一下,补全时弹出的下拉框其实是个view视图对象,因此你可以选择自己需要的视图以显示补全时想显示的自定义效果。

你可以通过completer和setCompleter获取和设置completer。

可以看到只要把我们用于补全输入的数据放入合适的model中,再把model设置给completer,就能实现补全功能了。

下面看个设置completer的例子:

# model是一个QStandardItemModel,后面我们也会使用这个model来设置completer completer = QCompleter() model.setParent(completer) completer.setModel(model) edit.setCompleter(completer)

另外completer得到的数据是经过验证的,所以我们无需关心数据的格式和合法性。

现在我们已经把QLineEdit的数据处理流程介绍了一遍,有了这些预备知识下面该实现CustomDateEdit了。

CustomDateEdit的实现

我们先来看代码,细节问题基本在注释中给出了说明:

class CustomDateEdit(QLineEdit): def __init__(self, parent=None): super().__init__(parent=parent) self.setInputMask(self.tr('9999年09月09日')) # 设置日期格式的inputMask validator = CustomDateValidator() self.setValidator(validator) # 设置validator # 设置completer self._completer = QCompleter() self.setCompleter(self._completer) self.completerModel = QStandardItemModel(parent=self._completer) self._completer.setModel(self.completerModel) # 预先填充一些待补全内容 self.addDateRecord("2019年03月14日") self.addDateRecord("2019年03月15日") def addDateRecord(self, text: str): """当有合法的输入被确认时就将其添加至completerModel,以便再次输入时补全 """ if self.completerModel.findItems(text): # 避免重复添加 return item = QStandardItem(text) self.completerModel.appendRow(item) def weekDayInfo(self, weekDay: int): """返回weekDay对应的名称,后面测试中会被使用 """ week = { 0: self.tr('周一'), 1: self.tr('周二'), 2: self.tr('周三'), 3: self.tr('周四'), 4: self.tr('周五'), 5: self.tr('周六'), 6: self.tr('周日'), } return week[weekDay]

整个dateEdit的实现也很简单,所有复杂的逻辑都已经交给了inputMask,验证器和completer,而我们唯一要做的是为completer添加新输入的合法的数据,这在类方法addDateRecord中完成了。

测试CustomDateEdit

实现CustomDateEdit之后,我们就要动手实现引论一节中的程序了。

前面已经说过,最终通过信号传递或者由槽函数获取到的值一定是通过了过滤和验证通过的值。所以想实现引论中的程序我们只需要正确处理CustomDateEdit的信号即可。

下面直接上测试代码:

class MainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent=parent) center = QWidget() self.dateEdit = CustomDateEdit() self.info = QLabel(self.tr('所选日期是')) self.dateEdit.textEdited.connect(lambda: self.info.setText(self.tr('所选日期是'))) # 输入结束后按回车触发该信号,同时只有输入数据通过过滤和验证后这个信号才会被发送 self.dateEdit.returnPressed.connect(self.calcWeekDay) layout = QVBoxLayout() layout.addWidget(self.dateEdit) layout.addWidget(self.info, alignment=Qt.AlignCenter) center.setLayout(layout) self.setCentralWidget(center) def calcWeekDay(self): # 计算所选日期是周几 t = arrow.get(self.dateEdit.text(), self.dateEdit.validator().dateFormat()) weekDayInfo = self.dateEdit.weekDayInfo(t.weekday()) self.info.setText(self.tr('所选日期是') + weekDayInfo) # 添加记录 self.dateEdit.addDateRecord(self.dateEdit.text()) if __name__ == '__main__': app = QApplication(sys.argv) win = MainWindow() win.show() app.exec_()

当用户输入一个完整的日期后,按下回车键,程序会自动计算结果并更新到下方的label上。很简单的程序,主要就是为了测试我们的CustomDateEdit:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsffpg.html