QTableView сортировка по нескольким колонкам одновременно и пример chap14 multisort из книги Земскова "Qt4 на примерах" |
Здравствуйте, гость ( Вход | Регистрация )
QTableView сортировка по нескольким колонкам одновременно и пример chap14 multisort из книги Земскова "Qt4 на примерах" |
Steklova Olga |
14.6.2013, 18:02
Сообщение
#1
|
Участник Группа: Участник Сообщений: 198 Регистрация: 27.9.2011 Из: Санкт-Петербург Пользователь №: 2912 Спасибо сказали: 5 раз(а) Репутация: 4 |
Здравствуйте
Понадобилось мне в QTableView отобразить записи таблицы БД, но отсортировать их не по одной колонке, как я раньше делала, а по нескольким одновременно. (Есть, например, в таблице поля A, B, C, D, F1, F2. Надо отсортировать записи по возрастанию значений поля A, записи с одинаковым А надо еще отсортировать по возрастанию B, с одинаковыми A и B - по возрастанию C, с одинаковыми A, B и C - по возрастанию D.) В книге Земскова есть пример multisort для QTableWidget. Там оператор, щелкая по заголовкам столбцов в том порядке, в каком хочет, выбирает, по каким колонкам надо отсортировать таблицу и как сортировать: по возрастанию или убыванию. Мне в программе пока не требуется, чтобы оператор выбирал, по каким полям сортировать таблицу. Мне надо жестко задать сортировку таблицы по возрастанию полей A, B, C, D. Как это сделать для QTableView? Не хочется использовать QTableWidget, у меня везде в программе используются QTableView, для которых установлены модели. А у QTableWidget нет метода setModel, есть только setItem. У меня, пока что, только одно предложение, как это можно сделать, но, по-моему, не самое удачное: Поля A, B, C, D у меня целые, при этом я знаю, сколько цифр максимально могут содержать эти поля (A - max 4 цифры, B - 3, C - 1, D - 1). Если сделать вычисляемое поле F_AAAABBBCD и записать туда A*10000 + B*100 + C*10 + D, то отсортировав таблицу по возрастанию этого поля, получим сортировку по полям A, B, C, D. Есть другие предложения? |
|
|
Litkevich Yuriy |
15.6.2013, 14:36
Сообщение
#2
|
разработчик РЭА Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: 94 |
См. Модели-посредники -> Пользовательские модели сортировки
Оговорка: если первичная модель выбирает данные из БД, то нужно делать от неё наследника, т.к. БД возвращает не все данные (их может быть слишком много), а выдаёт их порциями. В наследнике реализовать: - либо запрос с сортировкой - либо добавить собственную функцию для задания полей сортировки, например: setOrderField(QStringList), и при вызове select() у модели использовать эти поля. |
|
|
Steklova Olga |
17.6.2013, 11:23
Сообщение
#3
|
Участник Группа: Участник Сообщений: 198 Регистрация: 27.9.2011 Из: Санкт-Петербург Пользователь №: 2912 Спасибо сказали: 5 раз(а) Репутация: 4 |
См. Модели-посредники -> Пользовательские модели сортировки эта ссылка не работает, вот точнее Модели-посредникиНо я еще не разобралась, как использовать QSortFilterProxyModel. если первичная модель выбирает данные из БД, то нужно делать от неё наследника, т.к. БД возвращает не все данные (их может быть слишком много), а выдаёт их порциями. извините, ничего не понялаВ наследнике реализовать: - либо запрос с сортировкой - либо добавить собственную функцию для задания полей сортировки, например: setOrderField(QStringList), и при вызове select() у модели использовать эти поля. Предлагаю другой вариант. Если не использовать QSortFilterProxyModel, то, наверное, вот что можно сделать. Я использую модель MyModel, унаследованную от QSqlTableModel, переопределяю в ней методы flags, data, setData. Эта модель позволяет указывать setSort только для одного поля таблицы. Можно унаследовать модель MyModel не от QSqlTableModel, а от QSqlQueryModel. Такая модель позволит указать в setQuery сортировку по нескольким полям одновременно:
|
|
|
Litkevich Yuriy |
17.6.2013, 19:05
Сообщение
#4
|
разработчик РЭА Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: 94 |
эта ссылка не работает у меня работаетЭта модель позволяет указывать setSort только для одного поля таблицы. - либо добавить собственную функцию для задания полей сортировки, например: setOrderField(QStringList), и при вызове select() у модели использовать эти поля. |
|
|
Steklova Olga |
18.6.2013, 11:32
Сообщение
#5
|
Участник Группа: Участник Сообщений: 198 Регистрация: 27.9.2011 Из: Санкт-Петербург Пользователь №: 2912 Спасибо сказали: 5 раз(а) Репутация: 4 |
В наследнике реализовать: То есть, предлагаете переопределить метод select() у модели, унаследованной от QSqlTableModel ?- либо добавить собственную функцию для задания полей сортировки, например: setOrderField(QStringList), и при вызове select() у модели использовать эти поля. Вот что у меня получилось: код в моем классе:
код в исходникax:
Меня смущает, что я заремила d->initRecordAndPrimaryIndex() Сообщение отредактировал Steklova Olga - 18.6.2013, 13:07 |
|
|
Litkevich Yuriy |
18.6.2013, 11:42
Сообщение
#6
|
разработчик РЭА Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: 94 |
|
|
|
Steklova Olga |
18.6.2013, 12:24
Сообщение
#7
|
Участник Группа: Участник Сообщений: 198 Регистрация: 27.9.2011 Из: Санкт-Петербург Пользователь №: 2912 Спасибо сказали: 5 раз(а) Репутация: 4 |
Так я правильно поняла, что Вы
предлагаете переопределить метод select() у модели, унаследованной от QSqlTableModel ? В исходнике QSqlTableModel::select() я не понимаю: - что такое Q_D(QSqlTableModel); и можно ли выкинуть эту строку при переопределении ? - как добраться до d, чтобы обратиться к d->db ? Или никак не доберешься, и надо передавать db в наследуемый класс через параметр конструктора этого класса ? (хотя в моей программе можно обойтись вариантом QSqlQuery qu(query), так как у меня используется defaultConnection) - что делать с d->initRecordAndPrimaryIndex() ? Как это написать в переопределенном методе select() ? - переопределение select() ведет к необходимости переопределить еще какой-то метод в наследуемом классе ? В наследнике реализовать: Это как ?- запрос с сортировкой ------------------------------------------ У меня появилось предложение, как сделать в QTableView сортировку по нескольким колонкам одновременно, если для QTableView установлена модель MySqlTableModel, унаследованная от QSqlTableModel. Чтобы это сделать, переопределяем метод selectStatement(), метод select() не переопределяем. По-моему, этот вариант простой и правильный. Проверите? У меня работает Сообщение отредактировал Steklova Olga - 18.6.2013, 14:30 |
|
|
Litkevich Yuriy |
18.6.2013, 18:50
Сообщение
#8
|
разработчик РЭА Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: 94 |
Так я правильно поняла, что Вы ... нет.предлагаете переопределить метод select() у модели, унаследованной от QSqlTableModel ? идея была простая: добавить собственную функцию для задания полей сортировки, например: setOrderField(QStringList) дальше, нужно было заглянуть в метод select() чтобы понять, как на него влиять. Из приведённого тобой кода видно, что метод select() использует в качестве запроса результат метода selectStatement() его нужно будет переопределить,но ты уже сама до этого дошла: Чтобы это сделать, переопределяем метод selectStatement(), метод select() не переопределяем. осталось сделать метод setOrderField(QStringList), который позволит сделать твою модель гибче (её не надо будет переписывать в будущем)В исходнике QSqlTableModel::select() я не понимаю: d, Q_D(QSqlTableModel) - это из области d-указателей/Pimpl- что такое Q_D(QSqlTableModel); ... - как добраться до d, чтобы обратиться к d->db ? ... - что делать с d->initRecordAndPrimaryIndex() ? ... ... Они используются, чтобы создать вспомогательный класс описывающий "потраха" данного класса. А он, в свою очередь, чтобы обеспечить двоичную совместимость разделяемых библиотек (dll-ок для Виндовоза) от версии к версии. Положим у нас есть QCore.dll версии 4.4 если мы его усовершенствуем до версии 4.5, то хотим, чтобы программы собранные с 4.4 работали и с dll-ками 4.5. Но всякий раз когда мы добавляем виртуальный метод в класс, результат компиляции (двичный фал dll-ки) будет несовместим с предыдущей версией и программа скомпилированная с предыдущей версией dll-ки откажется работать. Для сохранения возможности изменения класса не изменяя его интерфейс придумали вспомогательный класс в котором вся каша и варится. d-указатели в официальной Qt Wiki (англ.) |
|
|
Текстовая версия | Сейчас: 29.3.2024, 19:02 |