I have a custom list, and on the view (with the QStyledItemDelegate
) I want display many things, including a text edit
(think about an online shopping cart where you have the items (photos and infos of them) and next to them you can change the quantity, but within a text edit, and not a spinbox).
This text edit should be able to communicate with the model. Currently I can only draw an empty textEdit, but I don't know how to connect it properly to the editorEvent
( and createEditor
, setEditorData
).
void CustomDelegate::paint(QPainter *painter,
const QStyleOptionViewItem &opt,
const QModelIndex &idx) const
{
// My other painting stuff (labels, shapes...)
QStyleOptionFrame panelFrame;
QLineEdit lineEdit;
panelFrame.initFrom(&lineEdit);
panelFrame.rect = rectLE;
panelFrame.state |= QStyle::State_Sunken;
QApplication::style()->drawPrimitive(QStyle::PE_PanelLineEdit, &panelFrame, painter);
}
QWidget *CustomDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
auto editor = new QLineEdit(parent);
editor->setText("test");
return editor;
}
void CustomDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
auto lineEdit = dynamic_cast<QLineEdit*>(editor);
if(lineEdit)
{
lineEdit->setText("test2");
}
}
As a the result I can only see an empty lineEdit
and can't really interact with it.
- If I would have multpiple
lineEdit
s inside onemodelIndex
delegate, how could I differentiate them in thesetEditorData
andcreateEditor
?
Thanks
CodePudding user response:
By default, editor in QAbstractItemView
is created only by edit triggers, those are set to it. Refer to docs
To make a view interactive in sense of rendered rows as regular widgets you can use a workaround.
I've used this approach with QListView
and QStyledItemDelegate
.
When i faced with same problem, i've tracked a viewport
's mouse move event, to get a QModelIndex
under the mouse cursor and if it was valid and different from previous value, i close an editor (if one was opened) and open a new one using methods QAbstractItemView::closePersistentEditor
and QAbstractItemView::openPersistentEditor
.
In my QStyledItemDelegate
derived class i've overrided createEditor
, setEditorData
and updateEditorGeometry
methods.
In createEditor
just create a widget, in updateEditorGeometry
setGeometry to editor, in setEditorData
get required data to render from QModelIndex
and set it to the editor widget.
The same widget class i've used to render all rows in view in paint
method.
CodePudding user response:
I forgot several things in my implementation:
To "interact" with the
lineEdit
theQt::ItemIsEditable
flag must be set in theQAbstractListModel::flags()
, otherwise the Editor functions in the Delegate won't get called.To reimplement
updateEditorGeometry()
where you specify thelineEdit
's position.To reimplement
setModelData()
where you can communicate with the model.To draw the text in the Delegate's
paint()
function afterdrawPrimitive
(drawPrimitive just draws the frame, but you want to draw the text you wrote in lineEdit as well. You can get it from the model)