Russian Qt Forum

Qt => Model-View (MV) => Тема начата: kambala от Ноябрь 26, 2014, 19:29



Название: QStyledItemDelegate рисовать самому только нужные части
Отправлено: kambala от Ноябрь 26, 2014, 19:29
Здравствуйте. Нужно в QListView отображать кастомные ячейки. Для этого используются делегаты насколько я понял (никогда раньше их не использовал).

Предположим, я хочу только заставить его отрисовывать многострочный текст, а все остальное пусть рисуется стандартным способом как это делает сам QStyledItemDelegate. Я наследуюсь от QStyledItemDelegate и в paint() пишу
Код
C++ (Qt)
painter->drawText(option.rect, Qt::TextWordWrap, index.data().toString());
Все прекрасно. А как теперь заставить суперкласс отрисовать все кроме текста? Или единственный способ — передирать исходники?

И еще вопрос на тему делегатов: может как-то можно создать виджет-шаблон, который будет отрисовываться в делегате? Сразу в нем задать лэйаут, чтобы руками координаты не считать.


Название: Re: QStyledItemDelegate рисовать самому только нужные части
Отправлено: Kurles от Ноябрь 26, 2014, 19:47
Создаёшь произвольный виджет в том же криейторе, и с помощью
Код
C++ (Qt)
void QWidget::render ( QPainter * painter, const QPoint & targetOffset = QPoint(), const QRegion & sourceRegion = QRegion(), RenderFlags renderFlags = RenderFlags( DrawWindowBackground | DrawChildren )
отрисовываешь его в paint() делегата.


Название: Re: QStyledItemDelegate рисовать самому только нужные части
Отправлено: vregess от Ноябрь 26, 2014, 21:30
Можно наподобие:

Код
C++ (Qt)
void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
   QStyleOptionViewItem opt = option;
   initStyleOption(&opt, index);
 
   ...
 
   const QWidget *widget = opt.widget;
   QStyle *style = widget ? widget->style() : QApplication::style();
   style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);
 
   .... (custom draw)
}
 

В общем основная идея в QStyle::draw*().


Название: Re: QStyledItemDelegate рисовать самому только нужные части
Отправлено: kambala от Ноябрь 26, 2014, 22:27
спасибо, попробую оба варианта.

с QStyle напрягает, что кода как-то много получается, и не самого понятного. Еще у него метод widget вроде в индексе справки есть, а в самой справке отсутствует... Это что за виджет такой? Дефолтный какой-то?


Название: Re: QStyledItemDelegate рисовать самому только нужные части
Отправлено: vregess от Ноябрь 27, 2014, 08:07
Не знаю, про какой widget ты говоришь.

Если тебе нужен делегат с базовым поведением, как "все остальные" - отрисовывать выделение, наведение, рамки и т.д. (как дефолтные делегаты), то QStyle, наверное, единственный способ. Ведь именно стиль рисует весь UI. Он будет работать ожидаемо на всех платформах и стилях.


Название: Re: QStyledItemDelegate рисовать самому только нужные части
Отправлено: kambala от Ноябрь 27, 2014, 13:58
const QWidget *widget = opt.widget; — я про это. что это за виджет?


Название: Re: QStyledItemDelegate рисовать самому только нужные части
Отправлено: vregess от Ноябрь 27, 2014, 14:22
Честно не помню, но по-моему это view, в котором рисует делегат (QListView в твоем случае).
И мы берем его стиль widget->style(), а если opt.widget не установлен (потому что это опциональное поле), то берем стиль приложения.
Как-то так.


Название: Re: QStyledItemDelegate рисовать самому только нужные части
Отправлено: kambala от Декабрь 01, 2014, 14:26
так, через рендер плюс http://stackoverflow.com/a/18983353/1971301 все получилось.

но теперь другая проблема: невозможно выделять мышкой текст (использую QPlainTextEdit). это решаемо?


Название: Re: QStyledItemDelegate рисовать самому только нужные части
Отправлено: kambala от Декабрь 01, 2014, 19:54
http://stackoverflow.com/questions/8893532/qlabel-text-not-selectble-even-when-i-set-qttextselectablebymouse-inside-qstyl вот вроде что-то нашел, буду пробовать.

но я не понимаю зачем мне эдитор для рид-онли контента. или эдитор — это просто название, необязательно чтобы он именно редактировал?


Название: Re: QStyledItemDelegate рисовать самому только нужные части
Отправлено: vregess от Декабрь 01, 2014, 20:51
Не понятно, почему должен выделяться текст. Ты же просто что-то рисуешь и нигде не обрабатываешь события.
Без создания editor'а вряд ли получится реализовать. Т.к. только так можно обработать события от пользователя в делегате.
Ну или перегружать обработку событий самого view.

или эдитор — это просто название, необязательно чтобы он именно редактировал?

да, не обязательно.


Название: Re: QStyledItemDelegate рисовать самому только нужные части
Отправлено: kambala от Декабрь 01, 2014, 21:27
вот оно что! спасибо.

почему-то нигде не видел толкового туториала по делегатам. пример про звездочку не покрывает многих вещей.


Название: Re: QStyledItemDelegate рисовать самому только нужные части
Отправлено: Bepec от Декабрь 01, 2014, 23:33
Проще выражаясь делегат без едитора просто отрисовывает картинку/виджет в соответствии с данными ячейки.
А едитор это полноценный виджет с сигналами слотами обработкой.


Название: Re: QStyledItemDelegate рисовать самому только нужные части
Отправлено: kambala от Декабрь 02, 2014, 16:12
createEditor() не вызывается. ЧЯДНТ? модель рид-онли, в листвью редактирование отключено (включение не помогает) и selectionStyle стоит None (смена тоже не влияет).


Название: Re: QStyledItemDelegate рисовать самому только нужные части
Отправлено: vregess от Декабрь 02, 2014, 17:30
Модель должна быть редактируемой, иначе view будет думать, что редактор не нужен, и у делегата не вызовется createEditor().

Цитировать
To enable editing in your model, you must also implement setData(), and reimplement flags() to ensure that ItemIsEditable is returned.

Еще надо посмотреть, какой триггер у view вызывает редактирование. См. QAbstractItemView::EditTrigger.


Название: Re: QStyledItemDelegate рисовать самому только нужные части
Отправлено: kambala от Декабрь 02, 2014, 17:52
ну таким образом вроде работает, но для этого нужно, чтобы этот эдит триггер срабатывал. а я хочу, чтобы лейбл с выбираемым текстом появлялся сразу, без всяких доп. действий. неужели такая элементарщина невозможна?..


Название: Re: QStyledItemDelegate рисовать самому только нужные части
Отправлено: Bepec от Декабрь 02, 2014, 18:03
Возможно. Нужно  QAbstractItemView::openPersistentEditor. Но там возникает проблема что он тупой и надо самому контролировать вызов только для видимых элементов, иначе взбесится.


Название: Re: QStyledItemDelegate рисовать самому только нужные части
Отправлено: kambala от Декабрь 02, 2014, 18:16
тогда может лучше просто setIndexWidget() делать на все айтемы?


Название: Re: QStyledItemDelegate рисовать самому только нужные части
Отправлено: vregess от Декабрь 02, 2014, 20:57
Да, можно и setIndexWidget(), особенно если элементов не много.