We start from a very simple table for the example, to which I put a colored background to the first column through a delegate.
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class TablaColor;
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
TablaColor* mitabla;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include "./tablacolor.h"
Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget)
{
ui->setupUi(this);
mitabla = new TablaColor(this);
}
Widget::~Widget()
{
delete ui;
}
colortable.h
#ifndef TABLACOLOR_H
#define TABLACOLOR_H
#include <QObject>
#include <QTableView>
class TablaColor : public QTableView
{
public:
TablaColor(QWidget *parent = nullptr);
};
#endif // TABLACOLOR_H
tablecolor.cpp
#include "tablacolor.h"
#include "modelotablacolor.h"
#include "delegadotablacolor.h"
TablaColor::TablaColor(QWidget *parent) : QTableView(parent)
{
setModel(new ModeloTablaColor);
setItemDelegateForColumn(0,new DelegadoTablaColor);
}
modeltablecolor.h
#ifndef MODELOTABLACOLOR_H
#define MODELOTABLACOLOR_H
#include <QAbstractTableModel>
class ModeloTablaColor : public QAbstractTableModel
{
public:
ModeloTablaColor(QObject *parent = nullptr);
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
};
#endif // MODELOTABLACOLOR_H
modeltablecolor.cpp
#include "modelotablacolor.h"
ModeloTablaColor::ModeloTablaColor(QObject *parent):QAbstractTableModel(parent)
{
}
QVariant ModeloTablaColor::data(const QModelIndex &index, int role) const
{
Q_UNUSED(role)
if (index.isValid())
{
return "dato";
}
return QVariant();
}
bool ModeloTablaColor::setData(const QModelIndex &index, const QVariant &value, int role)
{
Q_UNUSED(role)
Q_UNUSED(value)
if (index.isValid())
{
return true;
}
return false;
}
int ModeloTablaColor::rowCount(const QModelIndex &parent) const
{
Q_UNUSED (parent)
return 4;
}
int ModeloTablaColor::columnCount(const QModelIndex &parent) const
{
Q_UNUSED (parent)
return 2;
}
delegatecolortable.h
#ifndef DELEGADOTABLACOLOR_H
#define DELEGADOTABLACOLOR_H
#include <QStyledItemDelegate>
class DelegadoTablaColor : public QStyledItemDelegate
{
public:
DelegadoTablaColor(QObject *parent = nullptr);
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
};
#endif // DELEGADOTABLACOLOR_H
delegatecolortable.cpp
#include <QPainter>
#include "./delegadotablacolor.h"
DelegadoTablaColor::DelegadoTablaColor(QObject *parent): QStyledItemDelegate(parent)
{
}
void DelegadoTablaColor::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if (index.isValid())
{
painter->setPen(QPen(QColor(Qt::green)));
painter->setBrush(QBrush(QColor(Qt::gray)));
painter->drawRect(option.rect);
painter->setPen(QPen(QColor(Qt::darkYellow)));
painter->drawText(option.rect, Qt::AlignRight | Qt::AlignVCenter,index.data().toString());
}
else
{
QStyledItemDelegate::paint(painter, option, index);
}
}
QSize DelegadoTablaColor::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED (option)
Q_UNUSED (index)
return QSize();
}
The problem I have is that using delegates in this way, as the function is now implemented paint
, when I hover over a cell the highlighted color is not seen. That is, if the index is valid, I don't call the version paint()
of the base class.
If I call the base class every time (I'm removing the else
):
void DelegadoTablaColor::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if (index.isValid())
{
painter->setPen(QPen(QColor(Qt::green)));
painter->setBrush(QBrush(QColor(Qt::cyan)));
painter->drawRect(option.rect);
painter->setPen(QPen(QColor(Qt::magenta)));
painter->drawText(option.rect, Qt::AlignRight | Qt::AlignVCenter,index.data().toString());
}
QStyledItemDelegate::paint(painter, option, index);
}
The active cell is highlighted, but in return the base function renders the table content again. (the data is output twice, each represented with its own version of paint()
)
So the question is... how to keep the highlighted color when passing through the cell without duplicating the representation of the data?
If you are only going to change the properties that are used to do the painting, that is, text color, background color, text alignment that are associated with a role but you do not want to use a model for it, then the simplest thing is to override the initStyleOption method and draw the green border on top: