Я хочу получить целое число, хранящееся в [(1, 'cb'), (3, 'cd'), (7, 'ca'), (11, 'aa'), (22, 'bd')]
, когда я выбираю выпадающий автоматически полный элемент.PyQt QSortFilterProxyModel индекс от неправильной модели передан mapToSource?
Поскольку я использовал 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_())
обновление: Это будет решено, спасибо за помощь Авариса в #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()
becuase: " completionModel() на самом деле является прокси-модель на .MODEL()
вам не нужно возиться с mapToSource для этого. index.data (Qt.UserRole) должно дать вам этот номер независимо от того, какой индекс возвращается
просто FYI, вам редко приходится использовать mapToSource за пределами (прокси) модели. это в основном для внутреннего использования. надлежащий прокси-сервер должен перенаправить все соответствующие запросы из источника. так что вы можете использовать прокси-сервер, как если вы используете источник один -Avaris "