如何访问委托的 paint() 函数中的另一个索引?

How to access another index inside paint() function of delegate?

当鼠标悬停在 table 的一个单元格上时,我需要为该单元格的整行创建一个效果。这意味着我需要访问另一个索引。

在这种情况下,我做了一个for循环,运行从table的第一列到最后一列并为其设置效果。但它不起作用。当然是因为命令 drawText 没有任何输入参数作为索引。在这种情况下如何设置另一个索引的效果?

也欢迎其他解决方案。谢谢!

void TableDelegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const
{
  qDebug() << index.row() << index.column();
  TableDataRow::Type type = static_cast<TableDataRow::Type>( index.data( Qt::UserRole ).toInt() );

  QString text = index.data( Qt::DisplayRole ).toString();
  int row = index.row();

  if ( option.state & QStyle::State_MouseOver )
  {
     if ( type == TableDataRow::Type::Data )
     {
        painter->fillRect( QRect( 0, option.rect.topLeft().y(), option.rect.width()*numberOfColumns, option.rect.height() ), QColor( 249, 126, 18 ) );
        for ( int i = 0; i < numberOfColumns; i++ )
        {
           QModelIndex indexOfRow = index.sibling( row, i );
           painter->setPen( Qt::white );
           painter->drawText( option.rect, Qt::AlignVCenter | Qt::TextWordWrap, text );
        }
     }
  }
}

我了解到,如果鼠标位于行中的任何项目上,您想创建更改行文本颜色的效果,我认为为此没有必要使用委托,只需启用 mouseTracking 并覆盖 mouseMoveEvent 方法。

#include <QApplication>
#include <QMouseEvent>
#include <QStandardItemModel>
#include <QTableView>

class TableView: public QTableView{
public:
    TableView(QWidget *parent = nullptr):
        QTableView(parent)
    {
        setMouseTracking(true);
    }
protected:
    void mouseMoveEvent(QMouseEvent *event)
    {
        QModelIndex ix = indexAt(event->pos());
        if(mRow != ix.row()){
            changeRowColor(mRow);
            if(ix.isValid())
                changeRowColor(ix.row(), Qt::green, Qt::blue);
            mRow = ix.row();
        }
        QTableView::mouseMoveEvent(event);
    }

    void leaveEvent(QEvent *event)
    {
        changeRowColor(mRow);
        QTableView::leaveEvent(event);
    }
private:
    void changeRowColor(int row, const QColor & textColor=Qt::black, const QColor &backgroundColor=Qt::white){
        if(!model())
            return;
        for(int i=0; i< model()->columnCount(); i++){
            model()->setData(model()->index(row, i), textColor, Qt::ForegroundRole);
            model()->setData(model()->index(row, i), backgroundColor, Qt::BackgroundRole);
        }
    }
    int mRow = -1;
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    TableView w;

    QStandardItemModel model(5, 5);
    for(int i=0; i < model.rowCount(); i++){
        for(int j=0; j < model.columnCount(); j++){
            model.setItem(i, j, new QStandardItem(QString("%1-%2").arg(i).arg(j)));
        }
    }
    w.setModel(&model);
    w.show();
    return a.exec();
}

更新:

既然您已经使用 QAbstractTableModel 创建了自己的模型,那么您必须实现 setData()data() 方法来处理 Qt::ForegroundRoleQt::BackgroundRole 角色.

在我的示例中,每个项目都具有以下结构:

struct Item{
    QString text="";
    QBrush textColor=Qt::black;
    QBrush bgColor=Qt::white;
};

那么模型必须将数据保存在一个QList<QList<Item>> m_items;中,假设上面的方法应该如下:

QVariant TableModel::data(const QModelIndex &index, int role) const{
    if (!index.isValid())
        return QVariant();
    const Item & item = m_items[index.row()][index.column()];
    if (role == Qt::DisplayRole)
        return item.text;
    else if (role == Qt::ForegroundRole) {
        return item.textColor;
    }
    else if (role == Qt::BackgroundRole) {
        return item.bgColor;
    }
    else
        return QVariant();
}

bool TableModel::setData(const QModelIndex &index,
                         const QVariant &value, int role)
{
    if (!index.isValid())
        return false;
    Item & item = m_items[index.row()][index.column()];
    if(role == Qt::EditRole || role == Qt::DisplayRole){
        item.text = value.toString();
    }
    else if (role == Qt::ForegroundRole) {
        if(value.canConvert<QBrush>())
            item.textColor = value.value<QBrush>();
    }
    else if (role == Qt::BackgroundRole) {
        if(value.canConvert<QBrush>())
            item.bgColor = value.value<QBrush>();
    }
    else
        return false;
    emit dataChanged(index, index);
    return true;
}

完整的例子可以在下面找到link