Перехват событий QMouseEvent от иконки item'ов в QAbstractItemView
Материал из Wiki.crossplatform.ru
(Новая страница: «Иногда может потребоваться перехватывать события QMouseEvent от иконки ячейки таблицы или эле…»)
Следующая правка →
Версия 11:42, 20 октября 2010
Иногда может потребоваться перехватывать события QMouseEvent от иконки ячейки таблицы или элемента дерева. К примеру, на рисунке изображено некое дерево подключений, и нужно по двойному нажатию по иконке (только по иконке) листа произвести подключение, а по двойному нажатию по иконке ветки подключить все листья (здесь важно то, что в листе по мимо иконки содержится еще и чекер).
Qt не предоставляет стандартных средств для перехвата подобных событий. Хотя могли бы, так как весь необходимый функционал для этого есть. Находится он в protected области класса QItemDelegate. Поэтому ничто не запрещает нам его использовать.
Для реализации требуемого нам функционала создадим собственную реализацию QItemDelegate и переопределим в ней метод editorEvent
class IconEventFilterDelegate : public QItemDelegate { Q_OBJECT Q_DISABLE_COPY(IconEventFilterDelegate); public: explicit IconEventFilterDelegate(QObject *parent = 0); virtual bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index); signals: void iconDoubleClicked(const QModelIndex &index); };
![]() | Класс использует не документированные возможности Qt. |
IconEventFilterDelegate::IconEventFilterDelegate(QObject *parent) : QItemDelegate(parent) { } bool IconEventFilterDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) { if (event->type() == QEvent::MouseButtonDblClick) { QMouseEvent *me = static_cast<QMouseEvent*>(event); if (me->button() == Qt::LeftButton ) { QPixmap pixmap; QRect decorationRect; QVariant value = index.data(Qt::DecorationRole); if (value.isValid()) { pixmap = decoration(option, value); decorationRect = QRect(QPoint(0, 0), pixmap.size()); // Вичислим область занимаемую чекером. // Этого можно и не делать, если у вас нет чекера. И в качестве checkRect передать emptyRect. // Зато так код становится более общным, применимым к елементам как с чекером, так и без него QRect checkRect; Qt::ItemFlags flags = model->flags(index); if (flags.testFlag(Qt::ItemIsUserCheckable)) checkRect = check(option, option.rect, Qt::Checked); QRect emptyRect; doLayout(option, &checkRect, &decorationRect, &emptyRect, false); if (decorationRect.contains(me->pos())) { emit iconDoubleClicked(index); return true; } } } } return QItemDelegate::editorEvent(event, model, option, index); }