QTableWidget hover entire row without hard-coding background color
-
I've got a QTableWidget, and I want the entire row to be highlighted when mouse hovers on an item.
All the solutions I read from other questions hard code the background color in code, which is not what I want.
I'm using Qt stylesheet to set the background color of the hovered item:QTableWidget::item:hover { background-color: #27292b; }
And I tried to trick the items in a row into hovered state using a delegate:
#include <QStyledItemDelegate> class RowHoverDelegate: public QStyledItemDelegate { Q_OBJECT public: RowHoverDelegate(QTableWidget *tableWidget, QObject *parent = 0); void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; private: QTableWidget *m_tableWdt; }; // in the implementation file: RowHoverDelegate::RowHoverDelegate(QTableWidget *tableWidget, QObject *parent) : QStyledItemDelegate(parent), m_tableWdt(tableWidget) {} void RowHoverDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { if (option.state & QStyle::State_MouseOver) { QTableWidgetItem *hovItem = m_tableWdt->item(index.row(), index.column()); if (hovItem) { int row = hovItem->row(); int columnCount = m_tableWdt->columnCount(); for (int col = 0; col < columnCount; ++col) { QTableWidgetItem *item = m_tableWdt->item(row, col); if (item) { QModelIndex idx = m_tableWdt->model()->index(row, col); // copy option from the hovered item (opt is in State_MouseOver state) QStyleOptionViewItem opt = option; // update index and rect opt.index = idx; opt.rect = m_tableWdt->visualItemRect(item); QStyledItemDelegate::paint(painter, opt, idx); // paint the item } } return; } } QStyledItemDelegate::paint(painter, option, index); }
In the caller:
m_tableWdt = new QTableWidget(); // ... RowHoverDelegate *delegate = new RowHoverDelegate(m_tableWdt, m_tableWdt); m_tableWdt->setItemDelegate(delegate);
This delegate causes the hovered item and items on the left hand side of it change background, the right hand side items remains unchanged, strange. Can anyone explain this ?
-
OK, I solved it. The key is to update the viewport of the QTableWidget as stated here by Steffen
Here is the impoved delegate:
class RowHoverDelegate : public QStyledItemDelegate { Q_OBJECT public: RowHoverDelegate(QTableWidget *tableWidget, QObject *parent = 0); void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; protected slots: void onItemEntered(QTableWidgetItem *item); private: QTableWidget *m_tableWdt; int m_hoveredRow; };
Implementation:
RowHoverDelegate::RowHoverDelegate(QTableWidget *tableWidget, QObject *parent) : QStyledItemDelegate(parent), m_tableWdt(tableWidget), m_hoveredRow(-1) { // mouse tracking have to be true, otherwise itemEntered won't emit m_tableWdt->setMouseTracking(true); connect(m_tableWdt, SIGNAL(itemEntered(QTableWidgetItem *)), this, SLOT(onItemEntered(QTableWidgetItem *))); } void RowHoverDelegate::onItemEntered(QTableWidgetItem *item) { m_hoveredRow = item->row(); m_tableWdt->viewport()->update(); // force update } void RowHoverDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { QStyleOptionViewItem opt = option; if (index.row() == m_hoveredRow) { opt.state |= QStyle::State_MouseOver; } QStyledItemDelegate::paint(painter, opt, index); }
-
@linly said in QTableWidget hover entire row without hard-coding background color:
class RowHoverDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
RowHoverDelegate(QTableWidget *tableWidget, QObject *parent = 0);
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const;protected slots:
void onItemEntered(QTableWidgetItem *item);private:
QTableWidget *m_tableWdt;
int m_hoveredRow;
};class RowHoverDelegate : public QStyledItemDelegate { Q_OBJECT public: RowHoverDelegate(QTableWidget *tableWidget, QObject *parent = 0); void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; /* better to have override here */ protected slots: void onItemEntered(QTableWidgetItem *item); private: QTableWidget *m_tableWdt; int m_hoveredRow; };
-
@JoeCFD said in QTableWidget hover entire row without hard-coding background color:
override; /* override is needed here */
Hi Joe. Are you claiming this fixes anything? Although specifying
override
is desirable (I always do), it's not compulsory for anything, other than telling you if you've made a mistake. -