Centering DecorationRole icon in QTableView cell



  • I've subclassed QStyledItemDelegate and overrode the paint function. Then, I set the delegate appropriately. Here is the paint override code below:

    {
        QStyleOptionViewItem opt = option;
        opt.decorationAlignment = Qt::AlignHCenter;
        QStyledItemDelegate::paint(painter, opt, index);
    }
    

    Even so, the icon does not center. However, if I set:

    opt.decorationPosition = QStyleOptionViewItem::Top;
    

    ...then the icon does center horizontally. However, it is pushed up to the "top" which is not what I want. How can I center my icon horizontally and vertically?


  • Lifetime Qt Champion

    Hi,

    What if you use Qt::AlignCenter ?



  • @SGaist Unfortunately, that makes no difference.


  • Lifetime Qt Champion

    Can you provide a minimal compilable sample that shows this ?



  • Just to understand better, do you want the text to be painted overlapping the decoration?



  • @SGaist Sure, here it is:

    class Model : public QAbstractTableModel
    {
        int rows;
        int columns;
        QIcon flagIcon;
    
      public:
        explicit Model(QObject * parent = nullptr) : QAbstractTableModel(parent)
        {
            rows = 3;
            columns = 3;
            flagIcon.addFile(QCoreApplication::applicationDirPath() + "/flag.png");
        }
    
        int rowCount(const QModelIndex &parent = QModelIndex()) const { return rows; }
        int columnCount(const QModelIndex &parent = QModelIndex()) const { return columns; }
        QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const
        {
            if (role == Qt::DecorationRole)
                return flagIcon;
    
            else return QVariant();
        }
    };
    
    class FlagDelegate : public QStyledItemDelegate
    {
    public:
        FlagDelegate(QObject * parent) : QStyledItemDelegate(parent) { }
        void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
        {
            QStyleOptionViewItem opt = option;
            opt.decorationAlignment = Qt::AlignCenter;
            QStyledItemDelegate::paint(painter, opt, index);
        }
    };
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        QTableView table;
        table.setFixedWidth(400);
        table.setFixedHeight(400);
    
        Model model(&table);
        table.setModel(&model);
    
        FlagDelegate delegate(&table);
        table.setItemDelegate(&delegate);
    
        table.show();
    
        return a.exec();
    }
    

    Again, in the overridden paint method, the icon only centers if I set opt.decorationPosition to Top or Bottom.



  • @VRonin Sure, if that's what it takes. That's somewhat inapplicable to my situation because I have only one column that displays icons, but it never displays text.



  • The solution is to manually draw the pixmap of the icon with the painter object, like so:

    void FlagDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        QRect rect = option.rect;
        QIcon icon = qvariant_cast<QIcon>(index.data(Qt::DecorationRole));
        QPixmap pix = icon.pixmap( rect.size() *= 0.70 );
    
        QPoint p = QPoint((rect.width() - pix.width())/2, (rect.height() - pix.height())/2);
        painter->drawPixmap(rect.topLeft() + p, pix);
    }
    


  • void FlagDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
    const QStyle* style = option.widget ? option.widget->style() : qApp->style();
    style->drawPixmap(option.rect,Qt::AlignCenter,index.data(Qt::DecorationRole).value<QIcon>().pixmap(option.rect.size()));
    }
    
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.