使用QSortFilterProxyModel过滤时,在QListView中突出显示/选择第一个可见项

时间:2013-04-24 21:13:58

标签: python view model pyqt pyside

如果筛选结果不存在列表选择,那么我想自动突出显示第一个项目。我创建了方法force_selection(),如果没有选择任何内容,则突出显示第一个项目。我正在使用QListView.selectionModel()来确定选择索引。我尝试将force_selection()QLineEdit广告位相关联:textEdited(QString)textChanged(QString)。但是,似乎textChanged和代理刷新QListView之间存在时间问题。有时选择是在其他时候消失的。

那么,如果用户尚未做出选择,我将如何在代理过滤器期间强制选择(蓝色突出显示)?我的代码背后的想法是用户搜索项目,顶部项目是最佳结果,因此它被选中(除非他们手动选择过滤器视图中的另一个项目。)

You can find an image of the problem here.

重新创建问题:

  1. 使用Python 2.7执行示例脚本
  2. 不要在列表中选择任何内容(QLineEdit应该有焦点)
  3. 搜索'Red2',慢慢输入'R','e','d' - > Red1和Red2可见,Red1突出显示
  4. 输入数字'2'完成搜索 - > Red2不再突出显示/已选中
  5. 最终解决方案:

        from PySide import QtCore
        from PySide import QtGui
    
        class SimpleListModel(QtCore.QAbstractListModel):
    
            def __init__(self, contents):
                super(SimpleListModel, self).__init__()
                self.contents = contents
    
            def rowCount(self, parent):
                return len(self.contents)
    
            def data(self, index, role):
                if role == QtCore.Qt.DisplayRole:
                    return str(self.contents[index.row()])
    
        class Window(QtGui.QWidget):
    
            def __init__(self, parent=None):
                super(Window, self).__init__(parent)
    
                data = ['Red1', 'Red2', 'Blue', 'Yellow']
                self.model = SimpleListModel(data)
    
                self.view = QtGui.QListView(self)
    
                self.proxy = QtGui.QSortFilterProxyModel(self)
                self.proxy.setSourceModel(self.model)
                self.proxy.setDynamicSortFilter(True)
                self.proxy.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
                self.view.setModel(self.proxy)
    
                self.search = QtGui.QLineEdit(self)
                self.search.setFocus()
    
                layout = QtGui.QGridLayout()
                layout.addWidget(self.search, 0, 0)
                layout.addWidget(self.view, 1, 0)
    
                self.setLayout(layout)
    
                # Connect search to proxy model
                self.connect(self.search, QtCore.SIGNAL('textChanged(QString)'), 
                             self.proxy.setFilterFixedString)
    
                # Moved after connect for self.proxy.setFilterFixedString
                self.connect(self.search, QtCore.SIGNAL('textChanged(QString)'), 
                             self.force_selection)
    
                self.connect(self.search, QtCore.SIGNAL('returnPressed()'), 
                             self.output_index)
    
            # @QtCore.Slot(QtCore.QModelIndex)
            @QtCore.Slot(str)
            def force_selection(self, ignore):
                """ If user has not made a selection, then automatically select top item.
                """
                selection_model = self.view.selectionModel()
                indexes = selection_model.selectedIndexes()
    
                if not indexes:
                    index = self.proxy.index(0, 0)
                    selection_model.select(index, QtGui.QItemSelectionModel.Select)
    
            def output_index(self):
                print 'View Index:',self.view.currentIndex().row()
                print 'Selected Model Current Index:',self.view.selectionModel().currentIndex()
                print 'Selected Model Selected Index:',self.view.selectionModel().selectedIndexes()
    
    
        if __name__ == '__main__':
            import sys
    
            app = QtGui.QApplication(sys.argv)
            window = Window()
            window.show()
            sys.exit(app.exec_())
    

1 个答案:

答案 0 :(得分:1)

问题在于connect来电的顺序。您首先将textChanged连接到force_selection,因此首先调用它。但那时,不处理过滤器,也不更新代理。因此,您可以选择可能很快通过过滤删除的项目。

只需切换connect来电的顺序。

顺便说一下,您可能想在force_selection重新考虑您的逻辑。 currentIndex不一定与所选索引相对应。您可以通过输入red2并删除2来观察。您将同时选择Red1Red2。如果您想使用currentIndex而不是setCurrentIndex来处理select。如果您要处理选定的索引,那么您的条件应基于selectedRowsselectedIndexes