Home > other >  Qt: How to draw (and use) lineEdit inside delegate?
Qt: How to draw (and use) lineEdit inside delegate?

Time:06-16

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 lineEdits inside one modelIndex delegate, how could I differentiate them in the setEditorData and createEditor?

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:

  1. To "interact" with the lineEdit the Qt::ItemIsEditable flag must be set in the QAbstractListModel::flags(), otherwise the Editor functions in the Delegate won't get called.

  2. To reimplement updateEditorGeometry() where you specify the lineEdit's position.

  3. To reimplement setModelData() where you can communicate with the model.

  4. To draw the text in the Delegate's paint() function after drawPrimitive (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)

  • Related