Set Delegate for each cell in a QTableWidget?
-
Simplified example:
buttondelegate.h
#ifndef BUTTONDELEGATE_H #define BUTTONDELEGATE_H #include <QApplication> #include <QStyledItemDelegate> #include <QPushButton> #include <QPainter> class ButtonDelegate : public QStyledItemDelegate { Q_OBJECT #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0) Q_DISABLE_COPY_MOVE(ButtonDelegate) #else Q_DISABLE_COPY(ButtonDelegate) #endif public: explicit ButtonDelegate(QObject* parent) :QStyledItemDelegate(parent) { } void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE { Q_ASSERT(index.isValid()); QStyleOptionViewItem opt = option; initStyleOption(&opt, index); const QWidget *widget = option.widget; QStyle *style = widget ? widget->style() : QApplication::style(); QStyleOptionButton buttonOption = buttonOptions(opt,index); style->drawControl(QStyle::CE_PushButton, &buttonOption, painter, widget); } QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE { QStyleOptionViewItem opt = option; initStyleOption(&opt, index); return buttonRect(opt).size(); } QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const Q_DECL_OVERRIDE { return new QWidget(parent); } void setEditorData(QWidget *, const QModelIndex &) const Q_DECL_OVERRIDE { } void setModelData(QWidget *, QAbstractItemModel *, const QModelIndex &) const Q_DECL_OVERRIDE { } void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE { QStyleOptionViewItem opt = option; initStyleOption(&opt, index); editor->setGeometry(opt.rect); const QRect butRect = buttonRect(opt); QWidget* baseEditor = editor->findChild<QWidget*>("baseEditor"); Q_ASSERT(baseEditor); baseEditor->setGeometry(0,0,opt.rect.width()-butRect.width(),opt.rect.height()); QWidget* myButton = editor->findChild<QWidget*>("myButton"); Q_ASSERT(myButton); myButton->setGeometry(opt.rect.width()-butRect.width(), 0, butRect.width(),butRect.height()); } Q_SIGNALS: void clicked(const QModelIndex &index); protected: bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override { Q_ASSERT(event); Q_ASSERT(model); Qt::ItemFlags flags = model->flags(index); if ((option.state & QStyle::State_Enabled) && (flags & Qt::ItemIsEnabled)) { switch (event->type()){ case QEvent::MouseButtonRelease:{ QStyleOptionViewItem viewOpt(option); initStyleOption(&viewOpt, index); QMouseEvent *me = static_cast<QMouseEvent*>(event); if (me->button() == Qt::LeftButton) { currentIndex = index; clickedHelper(); } } break; default: break; } } return QStyledItemDelegate::editorEvent(event,model,option,index); } virtual QStyleOptionButton buttonOptions(const QStyleOptionViewItem &option, const QModelIndex &index, bool skipRct=false) const { QStyleOptionButton buttonOption; buttonOption.icon = m_buttonIcon; if(index.data(Qt::UserRole).toBool()) buttonOption.text = QString(QChar(0x23F8)); //pause button emoji else buttonOption.text = QString(QChar(0x25B6)); //play button emoji buttonOption.rect = skipRct ? QRect() : buttonRect(option); buttonOption.features = QStyleOptionButton::None; buttonOption.direction = option.direction; buttonOption.fontMetrics = option.fontMetrics; buttonOption.palette = option.palette; buttonOption.styleObject = option.styleObject; return buttonOption; } virtual QRect buttonRect(const QStyleOptionViewItem &option) const { return option.rect; } private: mutable QModelIndex currentIndex; QString m_buttonText; QIcon m_buttonIcon; void clickedHelper() { clicked(currentIndex); } }; #endif // BUTTONDELEGATE_H
main.cpp
#include <QApplication> #include <QTableWidget> #include "buttondelegate.h" int main(int argc, char *argv[]) { QApplication app(argc,argv); QTableWidget wid(10,2); for(int i=0;i<10;++i){ wid.setItem(i,0,new QTableWidgetItem(QStringLiteral("Item %1").arg(i+1))); } ButtonDelegate* buttonDelegate = new ButtonDelegate(&wid); QObject::connect(buttonDelegate,&ButtonDelegate::clicked,&wid,[&wid](const QModelIndex& index){ Q_ASSERT(index.model()==wid.model()); wid.model()->setData(index,index.data(Qt::UserRole).toBool() ? QVariant() : true,Qt::UserRole); }); wid.setItemDelegateForColumn(1, buttonDelegate); wid.show(); return app.exec(); }
-
@VRonin This one seems to be the solution I have been looking for. I will, however, have to hack my current code to using this solution. In case of any question I will reach out to you.
Thank you for taking so much time and having so much patience with me. I appreciate it.
-
@VRonin hi, I have finished modifying the delegate button so I can use it in my code and it works fine.
However, I am wondering how can I set a stylesheet for it. With my old QPushButton I had it like this:QPushButton* cancel_button = new QPushButton(this); cancel_button->setIcon(QIcon(QPixmap(":/Icons/cancel.png"))); cancel_button->setStyleSheet("QPushButton{background-color: transparent; background-repeat: none; border: none;} QPushButton:pressed{ background-color: transparent; }");
Can I do it with the delegate button? The reason I want to do this is because I want the the button to display only the icon I set for it.
Edit: I think I have solved it by going in the
QStyleOptionButton buttonOptions(const QStyleOptionViewItem &option, bool skipRct=false) const
function and change theQStyleOptionButton
features to flat:QStyleOptionButton buttonOption; buttonOption.features = QStyleOptionButton::Flat;