Qt C++:如何获取事件目标对象



有一个容器 Widget 实例 A,并且包含 Widget 实例 C1、C2、C3、...等在 A 内。

有一个插槽处理小部件 A 的 action_triggreed() 信号。

有没有办法确定哪个目标小部件 C1、C2、C3、...被点击了?这种必要性的原因是包含许多小部件,并且在每个小部件上使用connect()方法没有意义,这将需要50+行额外的连接语句,每个一个!

例如:考虑一个有很多按钮的QToolBox。您将如何使用 QToolBox action_triggered或类似信号来确定按下哪个按钮,而无需分别使用单个按钮的信号和插槽?

您可以使用

QObject::sender()函数。

void A::triggeredSlot() {
    QObject* obj = sender();
    QButton* but = qobject_cast<QButton*>(obj);
}

只需使用正确的类型等。

有几种通用方法。

第一个很简单 - 您应该将每个小部件的信号连接到插槽并检查sender()是什么。是的,用于连接的代码行。

第二种是使用一种映射器。每个小部件都连接到映射器,只有映射器连接到目标插槽。再次是代码行,至少在将小部件连接到映射器的部分中。有一个通用QSignalMapper或者您可以使用适合您的小部件的更具体的。例如,如果它们是按钮,则可以使用QButtonGroup类。每个按钮都在组中注册,只需要一个信号/插槽连接。

QButtonGroup group;
group->addButton(buttonC1,C1_ID);
...
group->addButton(buttonC1,Cn_ID);
connect(&group,SIGNAL(buttonClicked(QAbstractButton*),this,SLOT(buttonClicked(QAbstractButton*));

第三种方法是仅在母亲的小部件 A 上检测鼠标事件,然后遍历其所有子项并找到鼠标下的一个。更少的代码,您可以轻松添加新的小部件,但成本是在运行时遍历所有小部件。下面是一个示例。请注意,您可以将特定的QObject名称或属性添加到小部件 C1...这样,如果您只对给定类型的子小部件的一部分感兴趣,则可以过滤它们。

void mousePressEvent(QMouseEvent* event)
{
   if (event->button()==Qt::LeftButton)
   {
        QList<QToolButton*> buttons=findChildren<QToolButton*>(); // you can also use specific object names on the widgets under your interest
        foreach (QToolButton* button, buttons)
        {
           if (button->underMouse()) // you could try isDown() for button, but I'm not sure if that will work here
           {
               emit buttonClicked(button);
               break;
           }
        }
   }
}

好吧,您也可以尝试另一种方法。检测鼠标事件,获取光标位置并找到该位置上的子小部件。运行时成本不高。

void mousePressEvent(QMouseEvent* event)
{
   if (event->button()==Qt::LeftButton)
   {
       QPoint pt=mapFromGlobal(QCursor::pos());
       QWidget* child=childAt(pt);
       if (child)
       {
          emit childClicked(child);
       }           
   }
}

相关内容

  • 没有找到相关文章

最新更新