我想获取存储在 [(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 "
最佳答案
把正确的代码粘贴在这里以供引用
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_())
关于python - 来自错误模型的 PyQt QSortFilterProxyModel 索引传递给 mapToSource?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39259659/