如何单独捕捉QTreeWdiget鼠标点击事件
首先肯定想到的是安装eventFilter
安装后发现收不到鼠标点击事件,很幸运有人解答了, 得用treewidget->viewport()安装事件过滤器。
.h
#ifndef OBSERVERMOUSECLICKED_H
#define OBSERVERMOUSECLICKED_H
#include <QWidget>
class ObserverMousePressed : public QWidget
{
Q_OBJECT
public:
explicit ObserverMousePressed(Qt::MouseButtons, QWidget *parent);
signals:
void mousePressed();
public slots:
protected:
virtual void mousePressEvent(QMouseEvent *event) override;
virtual bool eventFilter(QObject *watched, QEvent *event) override;
private:
QObject * m_pTarget = nullptr;
Qt::MouseButtons m_buttons;
};
#endif // OBSERVERMOUSECLICKED_H
.cpp
#include <QMouseEvent>
#include "observermousepressed.h"
ObserverMousePressed::ObserverMousePressed(Qt::MouseButtons buttons,QWidget *parent) :
QWidget(parent), m_pTarget(parent),m_buttons(buttons)
{
Q_ASSERT(parent);
parent->installEventFilter(this);
this->setVisible(false);
}
void ObserverMousePressed::mousePressEvent(QMouseEvent *event)
{
QWidget::mousePressEvent(event);
}
bool ObserverMousePressed::eventFilter(QObject *watched, QEvent *event)
{
if(watched == m_pTarget)
{
if(event->type() == QEvent::MouseButtonPress)
{
if(reinterpret_cast<QMouseEvent *>(event)->buttons() == m_buttons )
{
emit mousePressed();
QWidget::eventFilter(watched, event);
return false;
}
}
}
return QWidget::eventFilter(watched, event);
}
use case
ObserverMousePressed *pProjectTreeLeftButtonPressed
= new ObserverMousePressed(Qt::LeftButton, ui->treeWidget_project->viewport());
如何得知鼠标点击的Item呢
我们知道eventFilter的调用位置是在事件函数之前的,这导致没法通过currentItem()方法得到当前点击的Item,因为currentItemchanged信号是在点击事件函数之后发出的,所以需要在eventFilter发出mousePressed信号后,获取鼠标点击处的Item。
这里有个小坑
connect(pProjectTreeLeftButtonPressed, &ObserverMousePressed::mousePressed,[=](){
ui->treeWidget_project->setCurrentItem(ui->treeWidget_project->itemAt(ui->treeWidget_project->viewport()->mapFromGlobal(QCursor::pos())));
ui->treeWidget_project->currentItem();
....
});
有什么用
如构造函数 explicit ObserverMousePressed(Qt::MouseButtons, QWidget *parent);
所示, 通过判断Qt::MouseButtons我们可以定向的检索到底是鼠标的哪些建点击的这个Item了;
因为QTreeWidget无论是左键点击还是右键点击, 都会触发currentItemChanged信号, 这会导致逻辑处理无法分化, 比如我们希望左键点击时刷新对应的属性视图, 右键单击时显示右键action菜单但是不刷新对应的属性视图,这种需求就无法实现.