Mousehover entire row selection in QTableView
-
Delegate is responsible for the cell only, so you need to report to highlight the view that the entire row.
You can do this in many ways ( for example )@
class IView {
public:
virtual void setMouseOver(bool flag, const QModelIndex& index) = 0;
}class MyView : public QTreeView, public IView {
public:
void setMouseOver(bool flag, const QModelIndex& index){
int row = index.row();for ( int col = 0; i < columnCount(); col++ ) { QStandartItem *item = model->item(row, col); if (flag ) item->setBackground(QBrush(QCloro("red"))); else item->setBackground(QBrush(QCloro("red"))); } }
};
class Delegate : public QSyledItemDelegate {
IView *view;void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const { bool isOver = option.state & QStyle::State_MouseOver; view->setMouseOver(isOver, index); }
};
@or something like this
@
class Delegate : public QSyledItemDelegate {
private:
int hoveredRow;void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const { if(option.state & QStyle::State_MouseOver) { hoveredRow = index.row(); } if ( hoveredRow == index.row(); ) { /// } else { } QSyledItemDelegate::paint(painter, option, index); }
};
@
-
-
-
@
#include <QtGui/QApplication>#include "TableView.h"
#include <QStandardItem>
#include <QStandardItemModel>int main(int argc, char *argv[])
{
QApplication a(argc, argv);QStandardItemModel model; for ( int col = 0; col < 3; col++ ) { QList<QStandardItem*> list; for ( int row = 0; row < 5; row++ ) { list.append(new QStandardItem); } model.appendColumn(list); } TableView view; view.setModel(&model); view.show(); return a.exec();
}
@@
#ifndef IVIEW_H
#define IVIEW_Hclass IView {
public:
virtual void setMouseOver(const int) =0;
};#endif // IVIEW_H
#ifndef TABLEVIEW_H
#define TABLEVIEW_H#include <QTableView>
#include <QMouseEvent>
#include <QStandardItem>#include "IView.h"
#include "Delegate.h"class TableView : public QTableView, public IView {
Q_OBJECTprivate:
int currHovered;void mouseMoveEvent(QMouseEvent *event); void disableMouseOver();
public:
TableView(QWidget *parent = 0);void setMouseOver(const int);
};
#endif // TABLEVIEW_H
#include "TableView.h"
#include <QDebug>
TableView::TableView(QWidget *parent) : QTableView(parent), currHovered(-1)
{
Delegate *delegate = new Delegate;
delegate->setView(this);setItemDelegate(delegate); setMouseTracking(true);
}
void TableView::setMouseOver(const int row)
{
if ( row == currHovered) return;QStandardItemModel *_model = static_cast<QStandardItemModel*>(model()); for ( int col = 0; col < _model->columnCount(); col++ ) { QStandardItem *item = _model->item(row, col); item->setBackground(QBrush(QColor("red"))); } if ( currHovered != -1 ) { disableMouseOver(); } currHovered = row;
}
void TableView::disableMouseOver()
{
QStandardItemModel _model = static_cast<QStandardItemModel>(model());
for ( int col = 0; col < _model->columnCount(); col++ )
{
QStandardItem *item = _model->item(currHovered, col);item->setBackground(QBrush(QColor("white"))); }
}
void TableView::mouseMoveEvent(QMouseEvent *event)
{// TODO: you need know when mouse are not in table rect // then you need disable over QTableView::mouseMoveEvent(event);
}
@@
#ifndef DELEGATE_H
#define DELEGATE_H#include <QStyledItemDelegate>
#include "IView.h"
class Delegate : public QStyledItemDelegate {
private:
IView *view;public:
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;void setView(IView *view) { this->view = view; }
};
#endif // DELEGATE_H
#include "Delegate.h"
#include <QDebug>
void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionViewItemV4 o = option;
initStyleOption(&o, index);if ( o.state & QStyle::State_MouseOver ) { view->setMouseOver(index.row()); } o.state &= ~QStyle::State_MouseOver; QStyledItemDelegate::paint(painter, o, index);
}
@p.s. I don't put this in the archive because it's very popular question.
p.s.s about previous code it was just idea ... not a full implementation.
p.s.s.s About this code, I'm sure it's not perfect (yes working, but not perfect), you can find a different idea or change the implementation. -
Hi Stima,
As mousehover is done but if i want selection and mousehover then how can we achieve this. As in Folder structure in windows 7 we can do selection (select one of the folder) and also mousehover we can do. How to achieve selection as well as mousehover ?
Thanks,
Neel -
Hi everyone, I have a problem with if ( o.state & QStyle::State_MouseOver ) ...
When mouse leaves a widget, it is still true...
I mean if we take a look on source code of QTableView, we can find there that a method drawCell
and two lines
@ if (index == hover)
opt.state |= QStyle::State_MouseOver;
@so it only sets the state up and not sets it down other hand, is it a BUG ?
And what can i do to not write a horrible scrap something like
@
void setHoveredIndex( QModelIndex index )
@into soure of my delegate
-
Hi Andre, thank you for quick reply.
So as you sad state is not keeping between drawing calls, but when mouse is leaving the widget it does not refresh the state, even if I call repaint after leaveEvent.
For example if we create a simple QComboBox, the behaviour on it's "popup-list" is absolutely the same, when mouse is leaving, it's still keeping last hovered index selected...