Comments 42
Задолбали вы своими КДПВ
минусы замечены?
минусы замечены?
Вы думаете, это из-за картинки? Без нее было бы совсе сухо, разве нет?
UFO just landed and posted this here
КДПВ — Картинка Для Привлечения Внимания
Статьи, в которых присутствует иллюстрация до ката, часто привлекают больше внимания, потому что люди очень любят визуальную информацию. Этим фактом иногда пользуются неподобающе: вставляют не очень тепло одетых дам и прочие изображения, которые не имеют к содержанию статьи никакого отношения, но моментально цепляют взгляд преобладающей мужской части аудитории сайта.
Статьи, в которых присутствует иллюстрация до ката, часто привлекают больше внимания, потому что люди очень любят визуальную информацию. Этим фактом иногда пользуются неподобающе: вставляют не очень тепло одетых дам и прочие изображения, которые не имеют к содержанию статьи никакого отношения, но моментально цепляют взгляд преобладающей мужской части аудитории сайта.
По чесноку пользоваться QAbstractListModel проще, чем городить QStandardItemModel, хотя последнюю бывает тоже делаю если данные статичные полностью, но в последнее время уже почти не нужно этого.
Вот когда дело до деревьев доходит, то тут начинаются самые сложности :)
Вот когда дело до деревьев доходит, то тут начинаются самые сложности :)
С деревьями да, интереснее. Я, в общем-то, даже сделал пример модели дерева, хотел включть сначала в статью, но в итоге, когда получилось 300 строк кода, а пример еще не был закончен, подумал, что если уж и рассказывать про это, то надо отдельную статью писать, про то как деревья делать. А тут больше такая критическая статья получилась. Если интерес у народа будет, напишу. Но пока в общем-то его не заметно особо.
А если гетерогенное дерево, то еще веселей.
UFO just landed and posted this here
Если вы про стиль написания, то я и сам им не очень доволен. Надеюсь, что со временем научучь писать лучше.
А если по поводу темы, то это как раз про Proxy модели. Там много всего интересного можно придумать, да.
А вот этот пост очень спорный. Хотя бы потому, что QStandardItemModel is not implemented as much efficient as possible, obviously.
При использовании же правильной QStringListModel и принятия мер против выкидывания оптимизирующим компиллятором обращений к QVector::operator[], результаты получаются немного другими:
А если по поводу темы, то это как раз про Proxy модели. Там много всего интересного можно придумать, да.
А вот этот пост очень спорный. Хотя бы потому, что QStandardItemModel is not implemented as much efficient as possible, obviously.
При использовании же правильной QStringListModel и принятия мер против выкидывания оптимизирующим компиллятором обращений к QVector::operator[], результаты получаются немного другими:
mod msecs 211
vec msecs 68
UFO just landed and posted this here
Я тему знаю, поэтому прочитал с легкостью и удовольствием. А вот интересно, что думают те, кто еще не познал вкус связки Model-View (без Controller).
Не помешал бы классический наглядный пример БД — модель — виджет.
Не помешал бы классический наглядный пример БД — модель — виджет.
Ну что будет. Если вы явно Контроллера не выделите — он у вас расползется по классу модели и классу формы. Рано или поздно случится бардак. Проходили, знаем.
Можно подробнее про бардак? А то пока не сталкивался, но и таблицы были не особо гигантские, с курсорами и фреймами заморачиваться не приходилось.
Какие операции над таблицами доступны в вашем приложении? Были ли иерархические данные? Приходилось ли делать специфические эдиторы? Была ли возможность одновременного редактирования нескольких записей? Что насчет одновременной работы нескольких клиентских приложений?
Операции — банальный CRUD.
Иерархия имеется, через поле parent_id.
Эдиторы есть, но не особо специфичные — текст (много строк), картинка, элемент (объект из другой таблицы).
Одновременного редактирования в одном приложении не было. Но в принципе возможно — кто последний, тот и папа.
Несколько клиентов работают, блокировки записей отсутствуют. Трагедии в этом нет, поскольку данные разбиты по владельцам, а владельцы разбиты по иерархии. Удаление записей только админом, юзеры могут лишь прятать записи.
Иерархия имеется, через поле parent_id.
Эдиторы есть, но не особо специфичные — текст (много строк), картинка, элемент (объект из другой таблицы).
Одновременного редактирования в одном приложении не было. Но в принципе возможно — кто последний, тот и папа.
Несколько клиентов работают, блокировки записей отсутствуют. Трагедии в этом нет, поскольку данные разбиты по владельцам, а владельцы разбиты по иерархии. Удаление записей только админом, юзеры могут лишь прятать записи.
А не было ли в одном представлении данных из нескольких таблиц? Foreign key? Каскадное удаление? Транзакции?
Дык, самодельный ORM же. Все есть. Транзакции только примитивно используются — автокоммит + вручную для пакетных операций типа импорта данных… Есть быстрый, но неудобный ОРМ (все общение с БД прописано в модели), есть простой, но не шибко оптимальный. На практике простого вполне хватает.
А вы с какой целью интересуетесь?
А вы с какой целью интересуетесь?
Да в свое время наелись по самые помидоры с этим MV в Qt. Когда класс главного окна перевалил за 3000 строк и еще пяток разных моделей по тыще, а баги стали появляться быстрее чем их исправляли, релиз отъехал на пару месяцев по срокам. Кое-что отрефакторили, кое-что так и живет.
Зато удалось структуру бизнес-данных полностью вывести во внешний XML вместе с поведением (QScript). Т.е. «движок на Qt» почти ничерта не знает о бизнес-логике. Это позволило в дальнейшем наращивать бизнес-логику очень быстро. Причем используя менее квалифицированный ресурс.
Зато удалось структуру бизнес-данных полностью вывести во внешний XML вместе с поведением (QScript). Т.е. «движок на Qt» почти ничерта не знает о бизнес-логике. Это позволило в дальнейшем наращивать бизнес-логику очень быстро. Причем используя менее квалифицированный ресурс.
Не совсем понял, почему главное окно оказалось перегружено кодом — оно же тупо отображает модели? Впрочем, всякое бывает.
У меня наоборот, довольно сложные и нудные модели, бизнес-логика где-то сбоку или на сервере, зато UI легок и приятен. И главное — сказочно гибок. Вот вздумалось перетасовать все виджеты и рассовать их по страницам — запросто, мышкой в дизайнере. И минимум кода, в основном всякие красивости и удобности, на работу не влияют.
У меня наоборот, довольно сложные и нудные модели, бизнес-логика где-то сбоку или на сервере, зато UI легок и приятен. И главное — сказочно гибок. Вот вздумалось перетасовать все виджеты и рассовать их по страницам — запросто, мышкой в дизайнере. И минимум кода, в основном всякие красивости и удобности, на работу не влияют.
Движок позволяет редактировать одновременно любое количество записей из любых таблиц, поддерживает для них закладки, переключаемые контексты, систему прав, имеет активную адресную строку по иерархии данных и еще кучу разнобразных рюшечек, придуманных воодушевленным специалистом по юзабилити. Одна беда — все это не было изначально запроектировано до мелочей, да и команда можно сказать набиралась опыта. Поэтому было реализовано как бог на душу положет.
Тем не менее в конце концов получилось прикольно, по крайней мере снаружи. А юзеру плевать что там внутри :)
Тем не менее в конце концов получилось прикольно, по крайней мере снаружи. А юзеру плевать что там внутри :)
Виджеты, это хорощо все. Но сами по себе они мало что из себя представляют. Где-то должна быть бизнес-логика, которая определяет поведение виджетов.
Локальная бизнес-логика работает с моделями. Серверная — с данными.
А поведение виджетов определяется моделями и самую малость кодом для отдельных случаев. Бизнес-логика к виджетам никакого отношения не имеет. Если уж так сильно надо порулить виджетами из скриптов — либо через модели, либо отдельная логика для UI.
Практика показывает, что как только UI связывается с данными через бизнес-логику — гибкость резко падает, а сложность поддержки возрастает. Приходится держать в голове всю цепочку «хранилище-данные-логика-представление», со всеми подвыпертами. А иначе сложность ограничена только одним звеном модель-хранилище, или модель-логика, или модель-представление. При этом звено модель-хранилище можно реализовать через ORM, и не париться. А модель-представление в Qt достаточно хорошо работает по дефолту.
А поведение виджетов определяется моделями и самую малость кодом для отдельных случаев. Бизнес-логика к виджетам никакого отношения не имеет. Если уж так сильно надо порулить виджетами из скриптов — либо через модели, либо отдельная логика для UI.
Практика показывает, что как только UI связывается с данными через бизнес-логику — гибкость резко падает, а сложность поддержки возрастает. Приходится держать в голове всю цепочку «хранилище-данные-логика-представление», со всеми подвыпертами. А иначе сложность ограничена только одним звеном модель-хранилище, или модель-логика, или модель-представление. При этом звено модель-хранилище можно реализовать через ORM, и не париться. А модель-представление в Qt достаточно хорошо работает по дефолту.
Модель не может, грубо, сама себя сортировать и фильтровать. Кто-то должен инициировать эти действия. Моделью управляет пользователь. И этот код управления не может целиком быть перемещен на саму модель.
Это QAbstractTableModel не может, а мой субкласс может. Если захочет. Есть же стандартная сортировка по значенияем колонок виджета. А вообще это все при выборке из хранилища фильтруется и сортируется. В одной из реализаций все это делается в самом классе модели. В другой — в отдельной фабрике/контроллере моделей. Оба способа работают.
Это я еще проксями не пользовался. С ними наверняка гораздо интереснее. =)
Видел такое. Действительно, если не выделять четко контроллеры, то через некоторое время начинается полный бардак.
Другое дело, что интерфейс модели в Qt достаточно богатый.
Другое дело, что интерфейс модели в Qt достаточно богатый.
Ну как богатый, мы когда дошли до пары десятков только собственных ролей в методе ::data() подумали что как-то все не очень ловко выходит.
А что не так с собственными ролями в
data()
? Я часто создаю их, когда в этом появляется необходимость. По-моему, это достаточно удобно, когда роль четко отражает род данных, которые по ней можно получить. Надо просто использовать единый их источник, чтобы ничто ни с чем не путалось.Спасибо за статью.
Мне было бы интересно почитать про совместное использование QGraphicsView и QTableView c проксями для табличных представлений. Как пример, есть граф, его надо отображать в QGraphicsView, узлы с их характеристиками в первом QTableView, ветви — во втором. Ну и прокси для сортировки\фильтрации по таблицам.
P.S. Если интересно, могу рассказать о чем угодно подробнее по теме работы с моделями. Предложения принимаются.
Мне было бы интересно почитать про совместное использование QGraphicsView и QTableView c проксями для табличных представлений. Как пример, есть граф, его надо отображать в QGraphicsView, узлы с их характеристиками в первом QTableView, ветви — во втором. Ну и прокси для сортировки\фильтрации по таблицам.
Одни плюсы, а минусов, при этом, не замечено.Очень смелое заявление. Да, все прекрасно работает, пока вы оперируете данными в объемах до ~1000 записей. Дальше начинаются проблемы.
Сходу могу накидать следующее:
1. Для сортировки и фильтрации предлагается QSortFilterProxyModel. Задумка хорошая но… Для сортировки и фильтрации данный класс выкачивает все сортируемые данные подмодели себе в память а затем внутри себя все это ворочает (а иначе просто не сделать). Если под этой моделью у вас лежит SQL-модель с десятками и сотнями тысяч записей — лучше забудьте о такой сортировке. Пишите сортировку и фильтрацию сами на SQL.
2. Иерархические модели. Поддержка иерархии есть (::parent()). Но такое ощущение, что прикручивали её сбоку после реализации прямоугольных моделей. На это намекает хотя бы тот момент что метод ::headerData(...) общий для всей модели (не зависит от индекса), а фактический набор колонок ::columnCount(...) зависит от узла иерархии.
3. Отрисовка иерархии в QTreeView. Прибито гвоздями, что визуальное отображение ветвей дерева делается всегда в нулевой колонке. Её можно кстати передвинуть в другое место, ветви тоже переедут. Может придирка, но реализация не выглядит продуманной.
4. QModelIndex. Класс так и провоцирует где-нибудь сохранить свой экземпляр с тем чтобы потом что-то с ним сделать. Этого делать ни в коем случае нельзя — индекс изменится при почти любом изменении модели. Есть QPersistentModelIndex для этих целей, но он тоже станет инвалидным, если модель переоткрыть, например.
5. Еще раз про SQL. Штатная реализация QSqlTableModel и QSqlQueryModel годятся только для простых случаев и небольших объемов данных. Если данных много и с ними нужны сложные манипуляции — пишите лучше сразу свои реализации под задачу. Со штатными только время потеряете.
В остальном MV вполне годный, пользоваться можно.
Про плюсы, это в контектсе использования MV вместо виджетов.
В общем, как и много где в Qt, есть много раздражающих моментов. Но, поскольку ничего лучше все равно нет, приходится пользоваться.
Пишите сортировку и фильтрацию сами на SQL.Не всегда запрашивать сервер БД каждый раз, когда пользователь выполняет сортировку — рационально. Просто вытягивание по сети этих десятков и сотен тычяч записей может оказаться дольше, чем даже не очень умелая сортировка руками. Так что, тут не все так одназначно. Иногда можно правильно отсортировать данные при запросе к БД таким образом, что любую другую сортировку можно получить, не выполняя полную пересортировку. В общем, тут далеко не все так однозначно.
Иерархические модели.О да, мне тоже всегда казалось, что они сделаны кривоваты. И этот
parent()
вечно не приткнуть никуда по-нормальному. QModelIndexОни хотели сделать макисмально легковесный класс. И у них, надо сказать, это получилось. В общем, надо, конечно, знать, как с ним работать, но ничего особо страшного нет. Вот реализация
QPersistentModelIndex
мне не очень-то нравится.В общем, как и много где в Qt, есть много раздражающих моментов. Но, поскольку ничего лучше все равно нет, приходится пользоваться.
Не всегда запрашивать сервер БД каждый раз, когда пользователь выполняет сортировку — рационально. Просто вытягивание по сети этих десятков и сотен тычяч записей может оказаться дольше, чем даже не очень умелая сортировка руками. Так что, тут не все так однозначно. Иногда можно правильно отсортировать данные при запросе к БД таким образом, что любую другую сортировку можно получить, не выполняя полную пересортировку. В общем, тут далеко не все так однозначно.Если вы сортируете или фильтруете в SQL-запросе, дишние данные остаются на сервере, не передаются. В чем плюс сортировки на SQL — повесил индексы и все работает как надо и памяти не расходует много. На клиенте придется либо иметь индексы (не знаю современных СУБД с внешними индексами) либо сортировать в памяти, т.е. все равно затащить все записи через сеть на клиента.
Это, в общем-то, зависит от того, сколько данных можно отфильтровать на сервере. Если количество данных, которые надо передать клиенту, велико, возможно их стоит скачать один раз, а не запрашивать каждый раз заново. Я просто сталкивался именно с такой постановкой задачи. Если на сервере удается эффективно отфильтровать большую чаасть данных, то вы, конечно, правы.
Sign up to leave a comment.
Использование моделей в Qt