Catch mouse event on tree widget item in QTreeWidget

时间:2016-04-21 21:55:47

标签: mouseevent qtreewidget qtreewidgetitem qt5.6

In tree widget I have following signal connected:

  connect(mTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem*, int)),
          SLOT(onItemClicked(QTreeWidgetItem*, int)));

where onItemClicked() slot is following:

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);
  }
}

However I can't catch itemClicked() signal and onItemClicked() never executed because top level items has push button widget (set with setItemWidget() method) which intercepts mouse event and child items contain container widgets which may have any widget combinations in them.

Is there a good method here to invoke this itemClicked() signal for both top level and child items of tree widget?

  • installEventFilter() for all widgets found in an item by something like following:
    QList<QWidget *> widgets = parentWidget.findChildren<QWidget *>();?
  • Or establish mouse event propagation somehow?
  • QCoreApplication::postEvent()?

How to organize such process better so all widgets process mouse event as they need to and TreeWidget issue SIGNAL(itemClicked()) as well?

Full sources to reproduce: https://github.com/akontsevich/WidgetBox

2 个答案:

答案 0 :(得分:0)

像这样创建事件过滤器:

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() - 也没有运气。有什么方法可以解决这个问题吗?

答案 1 :(得分:0)

因此,解决方案很简单,只需重新发送void itemClicked(QTreeWidgetItem *item, int column);中的PageEventFilter信号:

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。如果有人需要代码或想法,也会留下以前的答案。

相关问题