PyQt5中QLineEdit的QCompleter无有效高度且不显示匹配项
问题原因与解决方案
核心问题:QCompleter对TableModel的显示逻辑依赖Qt.DisplayRole与列配置
QCompleter默认会从TableModel的**第一列(index.column() == 0)**获取Qt.DisplayRole对应的数据来渲染弹窗列表。如果子类化模型存在以下情况,就会出现弹窗空但数据实际存在的现象:
1.
data()方法未正确返回Qt.DisplayRole对应的数据
字典列表转模型时,若只在自定义角色或其他角色中返回字符串,漏掉Qt.DisplayRole的返回,QCompleter拿不到显示用的文本,弹窗就会为空,但实际数据可通过其他角色访问(所以上下键能切换)。比如错误写法:def data(self, index, role=Qt.DisplayRole): if role == Qt.UserRole: return self.data_list[index.row()]["name"] # 未处理DisplayRole,返回None return None2.
columnCount()返回值错误
若columnCount()返回大于1的数值,但第一列没有填充数据,QCompleter只关注第一列,也会导致弹窗为空。如果补全只需要字典中的单个字段,应让columnCount()返回1,或显式指定QCompleter的completionColumn。3. 未指定QCompleter的
completionRole
若用自定义角色存储补全文本,需要显式告诉QCompleter用哪个角色取数据:completer.setCompletionRole(Qt.UserRole)否则QCompleter默认用
DisplayRole,拿不到数据就会显示空弹窗。
修复示例代码
from PyQt5.QtCore import QAbstractTableModel, Qt, QModelIndex from PyQt5.QtWidgets import QApplication, QLineEdit, QCompleter class DictTableModel(QAbstractTableModel): def __init__(self, data_list, parent=None): super().__init__(parent) self.data_list = data_list # 格式:[{"name": "xxx"}, ...] def rowCount(self, parent=QModelIndex()): return len(self.data_list) def columnCount(self, parent=QModelIndex()): return 1 # 仅保留一列用于补全 def data(self, index, role=Qt.DisplayRole): if not index.isValid(): return None row = index.row() if role == Qt.DisplayRole or role == Qt.EditRole: # 返回用于显示的补全文本 return self.data_list[row]["name"] return None if __name__ == "__main__": app = QApplication([]) data = [{"name": "Apple"}, {"name": "Banana"}, {"name": "Cherry"}] model = DictTableModel(data) line_edit = QLineEdit() completer = QCompleter(model, line_edit) # 若使用自定义角色存储数据,需添加此行: # completer.setCompletionRole(Qt.UserRole) line_edit.setCompleter(completer) line_edit.show() app.exec_()
额外注意点
- 确保
data()方法在Qt.DisplayRole下返回的是字符串类型,若返回整数、None等非字符串类型,QCompleter无法渲染显示。 - 按下上下键能切换,说明模型的
rowCount()配置正确,数据可被访问,核心问题还是显示用的角色或列的配置错误。
内容的提问来源于stack exchange,提问作者Ian Bailey-Mortimer
相关产品推荐
相关产品推荐

