Reputation: 361
When mouse is over a cell of a table, I need to create an effect for the whole row of that cell. That means I need to access to another index.
In this case I made a for loop, run from the first column to last column of the table and set effect for it. But it does not work. Off course because the command drawText does not have any input parameter as index. How can I set the effect for another index in this case?
Another solution is also welcomed. Thanks!
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 );
}
}
}
}
Upvotes: 2
Views: 442
Reputation: 244033
I understand that you want to create the effect of changing the color of the row text if the mouse is on any item in the row, I think that for this it is not necessary to use the delegate, just enable mouseTracking
and overwrite the mouseMoveEvent
method.
#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();
}
Update:
Since you have created your own model using QAbstractTableModel
then you must implement the setData()
and data()
methods to handle the Qt::ForegroundRole
and Qt::BackgroundRole
roles.
In my example, each item has the following structure:
struct Item{
QString text="";
QBrush textColor=Qt::black;
QBrush bgColor=Qt::white;
};
Then the model must save the data in a QList<QList<Item>> m_items;
, assuming the above the methods should be as follows:
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;
}
The complete example can be found in the following link
Upvotes: 1