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

时间:2016-03-17 02:44:26

标签: c++ qt events event-handling signals-slots

有一个容器Widget实例A,A中包含Widget实例C1,C2,C3,...等。

有一个插槽可以处理Widget A的action_triggreed()信号。

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

例如:考虑一个包含大量按钮的QToolBox。如何使用QToolBox action_triggered或类似信号确定按下哪个按钮,而不单独使用各个按钮的信号和插槽?

2 个答案:

答案 0 :(得分:1)

有一些通用方法。

第一个是直截了当的 - 您应该将每个小部件的信号连接到插槽并检查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);
       }           
   }
}

答案 1 :(得分:0)

您可以使用QObject::sender()功能。

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

只需使用正确的类型等。