Сортировка и фильтрация в QTableView, связь с моделью через Custom QSortFilterProxyModel
QTableView, QSortFilterProxyModel
Имеется QSqlQueryModel, делаю proxyModel->setSourceModel(model) и view->setModel(proxyModel).
view->setSortingEnabled(true) работает отлично, но пытаюсь по клику на строчку получить данные и понимаю что сортируется только view, а в модели сортировка не меняется.
То есть если была таблица с данными по возрастанию row1, row2, row3; я отсортировал row3, row2, row1 - по клику на row3 получаю доступ к row1.
Если у кого-то есть понимание поделитесь пожалуйста.
upd: помогли подсказки и поддержка пользователей и этот найденный пример.
custom_sort_filter_proxy_model.h
- #include <QApplication>
- #include <QtWidgets>
- class NameYearFilterProxyModel : public QSortFilterProxyModel{
- Q_OBJECT
- QRegExp nameRegExp;
- QRegExp yearRegExp;
- public:
- explicit NameYearFilterProxyModel(QObject* parent= nullptr):
- QSortFilterProxyModel(parent)
- {
- nameRegExp.setCaseSensitivity(Qt::CaseInsensitive);
- yearRegExp.setCaseSensitivity(Qt::CaseInsensitive);
- yearRegExp.setPatternSyntax(QRegExp::RegExp);
- nameRegExp.setPatternSyntax(QRegExp::RegExp);
- }
- bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override{
- QModelIndex nameIndex= sourceModel()->index(sourceRow, 0, sourceParent);
- QModelIndex yearIndex= sourceModel()->index(sourceRow, 1, sourceParent);
- QString name= sourceModel()->data(nameIndex).toString();
- QString year= sourceModel()->data(yearIndex).toString();
- return (
- name.contains(nameRegExp) && year.contains(yearRegExp)
- );
- }
- public slots:
- void setNameFilter(const QString& regExp){
- nameRegExp.setPattern(regExp);
- invalidateFilter();
- }
- void setYearFilter(const QString& regExp){
- yearRegExp.setPattern(regExp);
- invalidateFilter();
- }
- };
custom_sort_filter_proxy_model.cpp
- #include "custom_sort_filter_proxy_model.h"
- #include <QApplication>
- int main(int argc, char *argv[])
- {
- QApplication a(argc, argv);
- //set up GUI
- QWidget w;
- w.setWindowTitle("Custom SortFilterProxyModel");
- QVBoxLayout layout(&w);
- QHBoxLayout hLayout;
- QLineEdit lineEditName;
- QLineEdit lineEditYear;
- lineEditName.setPlaceholderText("name filter");
- lineEditYear.setPlaceholderText("year filter");
- lineEditYear.setValidator(new QRegExpValidator(QRegExp("[0-9]*")));
- lineEditYear.setMaxLength(4);
- hLayout.addWidget(&lineEditName);
- hLayout.addWidget(&lineEditYear);
- QTableView tableView;
- layout.addLayout(&hLayout);
- layout.addWidget(&tableView);
- //set up models
- QStandardItemModel sourceModel;
- NameYearFilterProxyModel filterModel;;
- filterModel.setSourceModel(&sourceModel);
- tableView.setModel(&filterModel);
- QObject::connect(&lineEditName, &QLineEdit::textChanged,
- &filterModel, &NameYearFilterProxyModel::setNameFilter);
- QObject::connect(&lineEditYear, &QLineEdit::textChanged,
- &filterModel, &NameYearFilterProxyModel::setYearFilter);
- QVector<QString> names{"Danny", "Christine", "Lars",
- "Roberto", "Maria"};
- for(int i=0; i<100; i++){
- QList<QStandardItem*> row;
- row.append(new QStandardItem(names[i%names.size()]));
- row.append(new QStandardItem(QString::number((i%9)+1980)));
- sourceModel.appendRow(row);
- }
- w.show();
- return a.exec();
- }
Так же решение со сбитой нумерацией строк в комментариях.
Do you like it? Share on social networks!
- Last comments
- AKApril 1, 2025, 11:41 a.m.Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
- VPMarch 9, 2025, 4:14 p.m.Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…
- ИМNov. 22, 2024, 9:51 p.m.Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
- Now discuss on the forum
- МАApril 1, 2025, 4:21 p.m.0ff763fe-4e50-455d-a3a6-5699c243b1a5_17_44_22_1.xml
- fFeb. 15, 2025, 1:46 p.m.Подскажите, пожалуйста! Как данный класс можно дополнить, чтобы созданные объекты можно было перемещать мышкой по сцене?
- Не запускается компьютер (точнее работает блок , но сам монитор вообще жесть)В общем я ничего с интернета не скачивала в последнее время. На компе никаких левых пр…
- Вопрос решен. Узнать QModelIndex элемента на который мы перетаскиваем другой элемент, можно с помощью функции indexAt(event->position().toPoint()) представления QTreeViev вызываемой в переопр…
А как получаете данные? Код приведите.
Возможно даже лишнего немного оставил, в целом картина такая:
По клику на одну из колонок
Я прошу прощения если от кода глаза слезятся, я учусь.
Без кода сложно сказать.
Лучше всего создать к примеру свои классы
В этих классах переопределить виртуальные методы ... взависимости от кода и проекта.
код я тут привёл https://evileg.com/en/forum/topic/1421/#post-8028
Страшно даже думать об этом, но если нет стандартных решений то придётся учиться.
Спасибо за ответ!
Выложети весь код.
Не понятно proxyOneModel ...
С вашего кода я понимаю (годаю) что proxyOneModel унаследован от QSqlQueryModel
Вы должны использовать класс QSortFilterProxyModel
Сортировка должна происходить в proxy , получать данные из model
Пытался адаптировать, чтобы не вникать в подробности, типа правила хорошего тона. Позже выложу по максимуму тогда. p.s., да, proxy это QSortFilterProxyModel
весь код как есть добавил в тело поста
Так. Убрал позорятину свою и без неё теперь видно. Заметил ошибку
тут model заменил на proxy:
всё заработало как надо!
спасибо всем кто отреагировал!!!
Да, не успел указать.
Спасибо! :) Фух, достала эта ошибка.
А что по решаемой задаче должно получаться? У меня такое чувство, что вы лишних моделей QSortFilterProxy понасоздавали и всё можно было в одну модель засунуть.
Может быть и лишние, но не понял как по-другому. Каждая модель для отдельного фильтра
ведь можно установить только один FilterKeyColumn для модели:
Посмотрите в сторону кастомной модели от QSortFilterProxyModel. В примерах Qt есть, Custom Sort/Filter Model Example. Так можно реализовать фильтрацию по нескольким полям, как вам и надо.
Попробую и тогда отпишусь по результату.
По поводу вашего когда.
1 - Согласен с МаркГлен ...
2 - Когда вы определяете/устанавливаете ширину колонок лучше использовать локальные константы (код лучше читается).
Пример:
3 - По поводу connect используете старый синтаксис.
Забегая наперед - у вас возникла ещё одна проблема с сортировкой нумерации строк.
Как уже было сказано ...
Необходимо переопределить виртуальный метод ...
Сложновато для меня, не понимаю что надо делать и что происходит. Наверное мне ещё рано.
Собезъянничал вот так:
basesortfilterproxymodel.h
basesortfilterproxymodel.cpp
Заменил везде QSortFilterProxyModel на BaseSortFilterProxyModel, ничего не меняется. Наверное если сходу не понятно, то бесполезно и пытаться разобраться? Или есть какие-то доки и мануалы которые можно почитать.
Пример смотрели? Там всё более-менее понятно.
Ну с сортировкой вертикальных заголовков разобрался теперь :)
Фильтры смотрю.
Доброго времени суток.
Вы начали правильно, но должны продолжить и дочитать документацию до конца.
Вам нужно разобраться с методом bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
Лучше всего создать проект-пример в котором запустить отладку проекта и разобраться.
1. Документация
2. Путь к примеру из самого QT Creator (у меня linux) - Qt/Examples/Qt-5.14.2/widgets/itemviews/customsortfiltermodel
Не сдавайтесь и будьте упрямее ...
... перечитайте ещё раз, если не поймёте запустите отладку проекта-примера и разберитесь в простом примере, а уж потом подумайте как применить к вашему проекту.
Итого, пришёл с одной проблемой, обнаружилось ещё несколько. Все были решены :) Но это я ещё остальной код не показывал. Понимаю что не хватает пару лет поработать джуном где-нибудь. Надо будет вам дать отревьюить как закончу.
Сделал изменения в теле топика.
Теперь ещё надо все миллион сигналов переписать по-новому.