[(1, 'cb'), (3, 'cd'), (7, 'ca'), (11, 'aa'), (22, 'bd')]
当我选择下拉自动完成项时,我想获取存储的整数。
因为我使用了 QSortFilterProxyModel,所以当使用向下键选择项目时,索引来自代理模型。
我在文档中阅读了我应该mapToSource
用来获取原始模型中的索引的文档,但是在这里我收到了一条错误消息index from wrong model passed to mapToSource
,并且index.row()
始终为 -1。我错过了什么?谢谢!
错误是:
row in proxy model 0
QSortFilterProxyModel: index from wrong model passed to mapToSource
row in original model -1
代码:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
import re
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
class MyModel(QStandardItemModel):
def __init__(self, parent=None):
super(MyModel, self).__init__(parent)
def data(self, index, role):
symbol = self.symbol_data[index.row()]
if role == Qt.DisplayRole:
return symbol[1]
elif role == Qt.UserRole:
return symbol[0]
def setup(self, data):
self.symbol_data = data
for line, name in data:
item = QStandardItem(name)
self.appendRow(item)
class MyGui(QDialog):
def __init__(self, parent=None):
super(MyGui, self).__init__(parent)
symbols = [(1, 'cb'), (3, 'cd'), (7, 'ca'), (11, 'aa'), (22, 'bd')]
model = MyModel()
model.setup(symbols)
layout = QVBoxLayout(self)
self.line = QLineEdit(self)
layout.addWidget(self.line)
self.setLayout(layout)
completer = CustomQCompleter()
completer.setModel(model)
completer.setCaseSensitivity(Qt.CaseInsensitive)
completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
completer.setWrapAround(False)
self.line.setCompleter(completer)
self.completer = completer
self.completer.highlighted[QModelIndex].connect(self.test)
# qApp.processEvents()
# QTimer.singleShot(0, self.completer.complete)
self.line.textChanged[QString].connect(self.pop)
def pop(self, *x):
text = x[0]
self.completer.splitPath(text)
QTimer.singleShot(0, self.completer.complete)
self.line.setFocus()
def test(self, index):
print 'row in proxy model', index.row()
print 'row in original model', self.completer.model().mapToSource(index).row()
# print 'line in original model:',
# self.completer.model().sourceModel().symbol_data[x[0].row()][0]
class CustomQCompleter(QCompleter):
def __init__(self, parent=None):
super(CustomQCompleter, self).__init__(parent)
self.local_completion_prefix = ""
self.source_model = None
self.first_down = True
def setModel(self, model):
self.source_model = model
self._proxy = QSortFilterProxyModel(
self, filterCaseSensitivity=Qt.CaseInsensitive)
self._proxy.setSourceModel(model)
super(CustomQCompleter, self).setModel(self._proxy)
def splitPath(self, path):
self.local_completion_prefix = str(path)
self._proxy.setFilterFixedString(path)
return ""
def eventFilter(self, obj, event):
if event.type() == QEvent.KeyPress:
'This is used to mute the connection to clear lineedit'
if event.key() in (Qt.Key_Down, Qt.Key_Up):
curIndex = self.popup().currentIndex()
if event.key() == Qt.Key_Down:
if curIndex.row() == self._proxy.rowCount()-1:
print 'already last row', curIndex.row()
if self._proxy.rowCount() == 1:
pass
else:
return True
else:
if curIndex.row() == 0:
print 'already first row'
return True
if curIndex.row() == 0 and self.first_down:
print 'already row 0 first'
self.popup().setCurrentIndex(curIndex)
self.first_down = False
return True
super(CustomQCompleter, self).eventFilter(obj, event)
return False
if __name__ == '__main__':
app = QApplication(sys.argv)
gui = MyGui()
gui.show()
sys.exit(app.exec_())
更新:已解决,感谢 Avaris 在#pyqt 中的帮助。事实证明,我可以这样做将索引映射到原始模型
proxy_index= self.completer.completionModel().mapToSource(index)
print 'original row:', self.completer.model().mapToSource(proxy_index).row()
甚至更好:
print 'data:', index.data(Qt.UserRole).toPyObject()
因为:“completionModel() 实际上是 .model() 上的代理模型
你不需要为此弄乱 mapToSource 。index.data(Qt.UserRole) 应该给你这个数字,不管返回哪个索引
仅供参考,您很少需要在(代理)模型之外使用 mapToSource 。它主要用于内部使用。适当的代理应转发来自源的所有相关查询。所以你可以像使用源代码一样使用代理 -Avaris "