Создание поля поиска QLineEdit для элементов, отображаемых в QListView
Я хочу создать поле поиска, которое фильтрует элементы, показанные в QListView. В основном пользователь может ввести "foo", и отображаются только элементы с" foo " в DisplayRole.
у меня уже есть несколько идей о том, как это сделать, но я подумал, что спрошу тех, кто более опытен, чем я.
моей идеей было бы использовать некоторые сигналы и слоты для установки фильтра в модели QAbstractItem и запуска update() в QListView.
есть ли какие-либо вспомогательные методы в QListView для фильтрации может я пропустил?
есть ли канонический способ справиться с этим, с которым я не сталкивался?
редактировать
текущий прогресс.
Я создал открытый слот под названием "updateFilter (QString)" в моем подклассе QFileSystemModel. Тогда Я ... --3-->
connect(myQLineEditSearch, SIGNAL(textChanged(QString)),
myQFileSysModel, SLOT(updateFilter(QString)));
это устанавливает фильтр, затем в моем QFileSystemModel:: data(...) метод, у меня есть:
void ComponentModel::updateFilter(QString filter)
{
_filter = filter;
emit layoutChanged();
}
QVariant ComponentModel::data(const QModelIndex &index, int role) const
{
QVariant result;
// if our search filter term is set and the item does not match,
// do not display item data. Searches are case insensitive
if (!_filter.isEmpty() &&
!QFileSystemModel::data(index, Qt::DisplayRole)
.toString().toLower().contains(_filter.toLower()))
{
return result;
}
result = QFileSystemModel::data(index, role);
return result;
}
Это почти там. "Глюк", над которым я работаю для того, где отображается объект. В настоящее время, если я применяю поиск, который соответствует 3-му элементу в списке, только первые две строки отображаются как пустые. Другими словами, он по-прежнему отображает строки для несогласованных элементов.
3 ответов
отвечая на свой собственный вопрос Для справки.
похоже, что здесь требуется QSortFilterProxyModel.
код выглядит примерно так:
QListView *myview = new QListView(this);
MyModel *model = new MyModel(this);
QSortFilterProxyModel *proxy = new QSortFilterProxyModel(this);
proxy->setSourceModel(model);
myview->setModel(proxy);
myview->setRootIndex(proxy->mapFromSource(model->index(model->rootPath()));
connect(filterLineEdit, SIGNAL(textChanged(QString)),
proxy, SLOT(setFilterFixedString(QString)));
единственная проблема, которую я вижу в этом, - это rootIndex, кажется, сбрасывается при вводе строки поиска. Я сообщу, когда выясню это.
это будет работать на QListWidget...
этот метод сохраняет все найденные элементы в QList, из которого вы можете позже прочитать их (например, чтобы показать их в том же или новом QListView):
void search_for_string( QString search_str )
{
QList<QListWidgetItem*> my_found_items;
for( int i = 0; i < my_list->count(); i++ )
{
QListWidgetItem* current = my_list->item( i );
if( current->text().contains( search_str ) )
{
my_found_items.append( current );
}
}
}
и при нажатии на "поиск" или что-то еще, вы называете это так:
search_for_string( my_line_edit->text() );
другое решение, которое работает для QListWidget:
void SpeciePropertiesListWidget::filter(QString filter_string)
{
hide_all();
QList<QListWidgetItem*> matches ( m_list->findItems(filter_string, Qt::MatchFlag::MatchContains) );
for(QListWidgetItem* item : matches)
item->setHidden(false);
}
void SpeciePropertiesListWidget::hide_all()
{
for(int row(0); row < m_list->count(); row++ )
m_list->item(row)->setHidden(true);
}
и затем подключите QLineEdit:
QLineEdit * m_filter_le = new QLineEdit(this);
SpeciePropertiesListWidget * list_widget = new SpeciePropertiesListWidget(this)
connect(m_filter_le, SIGNAL(textEdited(QString)), list_widget, SLOT(refresh_filter(QString)));