Using QWidget in Qt View

Problem: I have a simple QStringListModel model that I want to display in the view. However, I want each item in the view to be the custom QWidget that I created. I don’t understand why this is such a difficult problem! I searched the Internet for solutions, and although I find pieces here and there, not a single good solution meets all my needs.

The main code for customizing my model / view:

QStringList strings; // add some strings to the model QStringListModel* model = new QStringListModel(strings); QListView* view = new QListView; view->setModel(model); 

I have tried various attempts to do this to no avail.

Attempt # 1

I tried to subclass the new QItemDelegate object. Inside this object, I redefined the editor creation methods. I followed all the steps to configure this delegate. The problem is that when a view is populated with a model, it captures every element in the model in Qt :: DisplayRole, when I need to capture every element in Qt :: EditRole.

Attempt # 2

Another method I tried was to subclass QListView and override the setModel method to call setIndexWidget for each element in the model. My code looks something like this:

 void CustomListView::setModel(QAbstractItemModel* model) { QListView::setModel(model); for (int i = 0; i rowCount(); ++i) { QModelIndex index = model->index(i, 0); CustomWidget* widget = new CustomWidget; setIndexWidget(index, widget); } }
void CustomListView::setModel(QAbstractItemModel* model) { QListView::setModel(model); for (int i = 0; i rowCount(); ++i) { QModelIndex index = model->index(i, 0); CustomWidget* widget = new CustomWidget; setIndexWidget(index, widget); } } 

This worked before adding my CustomWidget object to each row as a list. To ensure that normal model data was not shown also under my CustomWidget objects, I also overridden CustomListView :: paintEvent (QPaintEvent * event) to do nothing. Again, this worked.

But now my main problem is that when the list is displayed, although my CustomWidgets are displayed on it correctly, the background of the list is solid white. I tried calling setAutoFillBackground (false) in CustomListView, but did nothing. I want my list view to have a transparent background.

Any feedback on this issue would be greatly appreciated. I spent a lot of time trying to get this to work! Thanks!

+4
source share
2 answers

I think I had a problem similar to creating user data in QStandardItemModel. What I did to solve it was to create a custom QStyledItemDelegate. In the createEditor method you can check:

 if( qVariantCanConvert<YourObject>(index.data(Qt::YourRole)) ) 

Then create your editor, which is actually a custom widget. And set its value with data from your model. To customize my widget, I used style sheets such as CustomWidget.setStylesheet ("background: blue");

In the drawing method of your delegate, if you want the same widget to perform exactly the same as with the editor.

 CustomWidget renderer; renderer.setText( index.data(Qt::DisplayRole).toString() ); renderer.resize(option.rect.size()); painter->save(); painter->translate(option.rect.topLeft()); renderer.render(painter); painter->restore(); 

You will have to process yourself openPersistentEditor and closePersistentEditor.

Hope this helps.

0
source

My suggestion is to stick with custom painting delegates.

See the Star delegate example . How you draw (see below) the way you want, and then edit using createEditor when you get focus.

 void StarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { if (qVariantCanConvert<StarRating>(index.data())) { StarRating starRating = qVariantValue<StarRating>(index.data()); if (option.state & QStyle::State_Selected) painter->fillRect(option.rect, option.palette.highlight()); starRating.paint(painter, option.rect, option.palette, StarRating::ReadOnly); } else { QStyledItemDelegate::paint(painter, option, index); } } 

The trap or cheat is that you can draw your widget without creating an editor instance or without having the widget in edit mode using drawControl() . See paint code in this question.

0
source

Source: https://habr.com/ru/post/1342170/


All Articles