2016-08-31 14 views
3

ドロップダウン自動完了アイテムを選択すると、[(1, 'cb'), (3, 'cd'), (7, 'ca'), (11, 'aa'), (22, 'bd')]に格納されている整数を取得します。誤ったモデルからのPyQt QSortFilterProxyModelインデックスがmapToSourceに渡されましたか?

私はQSortFilterProxyModelを使用していたので、項目を選択するためにdownキーを使用すると、インデックスはプロキシモデルのものです。

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でAvarisから助けてくれてありがとうを解決しています。それは私が

proxy_index= self.completer.completionModel().mapToSource(index) 
print 'original row:', self.completer.model().mapToSource(proxy_index).row() 

またはより良いオリジナルのモデルにインデックスをマッピングするためにこれを行うことができますことが判明:becuase

print 'data:', index.data(Qt.UserRole).toPyObject() 

:「 completionModelは()実際には.MODELのプロキシモデル(あります)

あなたはそのためmapToSourceと混乱する必要はありません。index.data(Qt.UserRole)は関係なく、単にFYI

を返されるインデックスのあなたにその番号を与える必要があり、あなたはめったに(プロキシ)モデルの外でmapToSourceを使う必要はありません。それは主に社内向けのものです。適切なプロキシは、ソースから関連するすべてのクエリを転送する必要があります。あなたがソース1 -Avaris 「

答えて

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) 

     # 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_()) 
関連する問題