在 QTreeWidget 中的树小部件项目上捕获鼠标事件
Catch mouse event on tree widget item in QTreeWidget
在树形小部件中,我连接了以下信号:
connect(mTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem*, int)),
SLOT(onItemClicked(QTreeWidgetItem*, int)));
其中 onItemClicked()
插槽如下:
void WidgetBox::onItemClicked(QTreeWidgetItem *item, int )
{
int index = getPageIndex(item);
setCurrentIndex(index);
}
int WidgetBox::getPageIndex(QTreeWidgetItem *item)
{
if (!item) return -1;
QTreeWidgetItem *parent = item->parent();
if(parent) // Parent is top level item
{
return mTreeWidget->indexOfTopLevelItem(parent);
}
else // Current item is top level
{
return item->treeWidget()->indexOfTopLevelItem(item);
}
}
void WidgetBox::setCurrentIndex(int index)
{
if (index != currentIndex() && checkIndex(index))
{
mTreeWidget->setCurrentItem(mTreeWidget->topLevelItem(index));
emit currentIndexChanged(index);
}
}
但是我无法捕获 itemClicked()
信号并且 onItemClicked()
从未执行过,因为顶级项目有按钮小部件(使用 setItemWidget()
方法设置)拦截鼠标事件和子项目包含容器小部件,其中可能包含任何小部件组合。
这里有没有一种好的方法可以为树形小部件的顶级项和子项调用此 itemClicked()
信号?
- installEventFilter() 用于通过以下方式在项目中找到的所有小部件:
QList<QWidget *> widgets = parentWidget.findChildren<QWidget *>();
?
- 或以某种方式建立mouse event propagation?
- QCoreApplication::postEvent()?
如何更好地组织此类过程,以便所有小部件根据需要处理鼠标事件以及 TreeWidget 问题 SIGNAL(itemClicked())
?
Full sources to reproduce: https://github.com/akontsevich/WidgetBox
像这样创建了事件过滤器:
class PageEventFilter : public QObject
{
Q_OBJECT
public:
PageEventFilter(QObject *parent, QTreeWidgetItem *item);
protected:
bool eventFilter(QObject *obj, QEvent *event);
private:
QTreeWidgetItem *mItem;
};
bool PageEventFilter::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::MouseButtonPress)
{
// Emitate mouse event for parent QTreeWidget
QMouseEvent *oldEvent = (QMouseEvent *)event;
QRect itemRect = mItem->treeWidget()->visualItemRect(mItem);
QPointF mousePos(itemRect.x() + 1, itemRect.y() + 1);
QMouseEvent *newEvent = new QMouseEvent(oldEvent->type(),
mousePos,
oldEvent->button(),
oldEvent->buttons(),
oldEvent->modifiers());
QCoreApplication::postEvent(mItem->treeWidget(), newEvent);
return false; // Sent event to the object (do not filter it)
}
else
{
// standard event processing
return QObject::eventFilter(obj, event);
}
}
将其安装到树形小部件项目中的按钮。它创建鼠标事件并将其发送(模仿)到树形小部件,但是树形小部件仍然不发送 itemClicked(QTreeWidgetItem*, int) 信号。可能是什么问题?鼠标位置不对?试图将事件发送到 viewport() - 也不走运。有什么办法解决这个问题吗?
所以解决方案很简单,只需在 PageEventFilter
中重新发送 void itemClicked(QTreeWidgetItem *item, int column);
信号即可:
PageEventFilter::PageEventFilter(QObject *parent, QTreeWidgetItem *item)
: QObject(parent)
, mItem(item)
{
connect(this, SIGNAL(itemClicked(QTreeWidgetItem*,int)),
mItem->treeWidget(), SIGNAL(itemClicked(QTreeWidgetItem*,int)));
}
bool PageEventFilter::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::MouseButtonPress)
{
// Resend signal to QTreeWidget
emit itemClicked(mItem, 0);
return false; // Send event to the object (do not filter it)
}
else
{
// standard event processing
return QObject::eventFilter(obj, event);
}
}
P.S. Will leave previous answer as well if somebody needs code or idea.
在树形小部件中,我连接了以下信号:
connect(mTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem*, int)),
SLOT(onItemClicked(QTreeWidgetItem*, int)));
其中 onItemClicked()
插槽如下:
void WidgetBox::onItemClicked(QTreeWidgetItem *item, int )
{
int index = getPageIndex(item);
setCurrentIndex(index);
}
int WidgetBox::getPageIndex(QTreeWidgetItem *item)
{
if (!item) return -1;
QTreeWidgetItem *parent = item->parent();
if(parent) // Parent is top level item
{
return mTreeWidget->indexOfTopLevelItem(parent);
}
else // Current item is top level
{
return item->treeWidget()->indexOfTopLevelItem(item);
}
}
void WidgetBox::setCurrentIndex(int index)
{
if (index != currentIndex() && checkIndex(index))
{
mTreeWidget->setCurrentItem(mTreeWidget->topLevelItem(index));
emit currentIndexChanged(index);
}
}
但是我无法捕获 itemClicked()
信号并且 onItemClicked()
从未执行过,因为顶级项目有按钮小部件(使用 setItemWidget()
方法设置)拦截鼠标事件和子项目包含容器小部件,其中可能包含任何小部件组合。
这里有没有一种好的方法可以为树形小部件的顶级项和子项调用此 itemClicked()
信号?
- installEventFilter() 用于通过以下方式在项目中找到的所有小部件:
QList<QWidget *> widgets = parentWidget.findChildren<QWidget *>();
? - 或以某种方式建立mouse event propagation?
- QCoreApplication::postEvent()?
如何更好地组织此类过程,以便所有小部件根据需要处理鼠标事件以及 TreeWidget 问题 SIGNAL(itemClicked())
?
Full sources to reproduce: https://github.com/akontsevich/WidgetBox
像这样创建了事件过滤器:
class PageEventFilter : public QObject
{
Q_OBJECT
public:
PageEventFilter(QObject *parent, QTreeWidgetItem *item);
protected:
bool eventFilter(QObject *obj, QEvent *event);
private:
QTreeWidgetItem *mItem;
};
bool PageEventFilter::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::MouseButtonPress)
{
// Emitate mouse event for parent QTreeWidget
QMouseEvent *oldEvent = (QMouseEvent *)event;
QRect itemRect = mItem->treeWidget()->visualItemRect(mItem);
QPointF mousePos(itemRect.x() + 1, itemRect.y() + 1);
QMouseEvent *newEvent = new QMouseEvent(oldEvent->type(),
mousePos,
oldEvent->button(),
oldEvent->buttons(),
oldEvent->modifiers());
QCoreApplication::postEvent(mItem->treeWidget(), newEvent);
return false; // Sent event to the object (do not filter it)
}
else
{
// standard event processing
return QObject::eventFilter(obj, event);
}
}
将其安装到树形小部件项目中的按钮。它创建鼠标事件并将其发送(模仿)到树形小部件,但是树形小部件仍然不发送 itemClicked(QTreeWidgetItem*, int) 信号。可能是什么问题?鼠标位置不对?试图将事件发送到 viewport() - 也不走运。有什么办法解决这个问题吗?
所以解决方案很简单,只需在 PageEventFilter
中重新发送 void itemClicked(QTreeWidgetItem *item, int column);
信号即可:
PageEventFilter::PageEventFilter(QObject *parent, QTreeWidgetItem *item)
: QObject(parent)
, mItem(item)
{
connect(this, SIGNAL(itemClicked(QTreeWidgetItem*,int)),
mItem->treeWidget(), SIGNAL(itemClicked(QTreeWidgetItem*,int)));
}
bool PageEventFilter::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::MouseButtonPress)
{
// Resend signal to QTreeWidget
emit itemClicked(mItem, 0);
return false; // Send event to the object (do not filter it)
}
else
{
// standard event processing
return QObject::eventFilter(obj, event);
}
}
P.S. Will leave previous answer as well if somebody needs code or idea.