Je souhaite obtenir l'entier stocké dans [(1, 'cb'), (3, 'cd'), (7, 'ca'), (11, 'aa'), (22, 'bd')]
lorsque je sélectionne l'élément déroulant automatique terminé.Indice PyQt QSortFilterProxyModel du mauvais modèle transmis à mapToSource?
Parce que j'ai utilisé un QSortFilterProxyModel, lorsque vous utilisez la touche Bas pour sélectionner l'élément, l'index provient du modèle de proxy.
J'ai lu dans la documentation que je devrais utiliser mapToSource
pour obtenir l'index dans le modèle original, mais ici j'ai reçu un message d'erreur index from wrong model passed to mapToSource
et le index.row()
est toujours -1. Qu'est-ce que je rate? Merci!
L'erreur est:
row in proxy model 0
QSortFilterProxyModel: index from wrong model passed to mapToSource
row in original model -1
Code:
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_())
mise à jour: Ceci est résolu, Merci pour l'aide de Avaris à #pyqt. Il se trouve que je peux faire pour cartographier l'index modèle original
proxy_index= self.completer.completionModel().mapToSource(index)
print 'original row:', self.completer.model().mapToSource(proxy_index).row()
ou mieux encore:
print 'data:', index.data(Qt.UserRole).toPyObject()
becuase: " completionModel() est en fait un modèle de procuration sur .model()
vous n'avez pas besoin de jouer avec mapToSource pour cela. index.data (Qt.UserRole) devrait vous donner ce nombre, quel que soit l'indice est retourné
juste un FYI, vous avez rarement besoin d'utiliser mapToSource en dehors d'un modèle (proxy). C'est principalement pour un usage interne. un mandataire approprié doit transmettre toutes les requêtes pertinentes de la source. de sorte que vous pouvez utiliser le proxy comme si vous utilisez la source un -Avaris "