c++qtqt5qtablewidgetqtablewidgetitem

How to prevent too aggressive text elide in QTableview?


I have an issue with text elide in Qt being too aggressive in a table, see picture. enter image description here

The cell with the full figure 0.8888.... I've edited since the QTableWidget was shown, the others are are as the were when the QTableWidget was created. It seems like the elide is calculated on a lesser width that is actually the case. How can I prevent this and get proper text elide immediately when the widget becomes visible?

Simplifide code to reproduce:

QTableWidget *tableWidget;
tableWidget = new QTableWidget(Dialog);
tableWidget->setGeometry(QRect(40, 20, 256, 192));
tableWidget->setRowCount(4);
tableWidget->setColumnCount(1);
tableWidget->setItem(0, 0, new QTableWidgetItem("0.234823489789234"));

and result

enter image description here

Note that I would like to avoid doing the elide myself since the user can edit the value. Doing the elide myself would then mean putting back the real value when editing starts, perhaps via delegates. Would be complicated.


Solution

  • When everything just worked...

    ...the solution could have been as simple as disabling the elide in the QTableWidget and set directly an elided string as item's text like that:

    tableWidget->setTextElideMode(Qt::ElideNone);
    tableWidget->setItem(0, 0, new QTableWidgetItem(tableWidget->fontMetrics().elidedText("0.234823489789234", Qt::ElideRight, tableWidget->columnWidth(0))));
    

    Unfortunately, QTableWidget (or maybe it is QStyledItemDelegate) does not respect the QAbstractItemView::textElideMode property.

    Thus, you need to do it the hard way, i.e. using delegates. Do not worry though, it is not much more complicated.

    Solution

    1. Subclass QStyledItemDelegate and reimplement its paint method like this:

       void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
                            const QModelIndex &index) const
       {
           if (!index.isValid())
               return;
      
           QStyleOptionViewItem opt = option;
           initStyleOption(&opt, index);
           int padding = 3;
      
           painter->save();
           painter->setClipRect(opt.rect);
           opt.rect = opt.rect.adjusted(padding, padding, -padding, -padding);
           painter->drawText(opt.rect, Qt::AlignLeft | Qt::AlignVCenter,
                             opt.fontMetrics.elidedText(opt.text, Qt::ElideRight,
                                                        opt.rect.width()));
           painter->restore();
      
           opt.rect = option.rect;
           opt.textElideMode = Qt::ElideNone;
           opt.text = "";
      
           QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter);
       }
      

    Feel free to change the padding to a suitable value.

    1. Set the tableWidget's delegate for the desired column like this:

       tableWidget->setItemDelegateForColumn(0, new Delegate(this));
      

    where Delegate is your QStyledItemDelegate subclass.

    Result

    The result of this modification is a column with a properly elided text.

    Table with a properly elided text