3

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 "

Répondre

1

collez le bon code pour référence

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) 

     # 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 completion model', index.row() 
     print 'data:', index.data(Qt.UserRole).toPyObject() 

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_())