将参数绑定到信号/插槽

Ahm*_*mad 10 c++ qt

我基本上有多个事件信号,我想连接到同一个插槽.我想知道的是如何将基于字符串的参数传递到同一个插槽,以便插槽知道这个信号来自哪个.一种替代方案是制作与信号一样多的插槽,然后以1:1的方式连接它们,但考虑到所有处理的代码非常相似,这是有效的.我尝试过这样做,但是我遇到了一些错误:

connect(selecter1,SIGNAL(selected(QString)),this,SLOT(backgroundTypeChoiceMade(QString)));
connect(button1,SIGNAL(clicked()),this,SLOT(backgroundTypeChoiceMade("button1")));
connect(button2,SIGNAL(clicked()),this,SLOT(backgroundTypeChoiceMade("button2")));
Run Code Online (Sandbox Code Playgroud)

该错误与我在最后2个命令中传递的参数有关..并且backgroundTypeChoiceMade声明如下:

void backgroundTypeChoiceMade(QString);
Run Code Online (Sandbox Code Playgroud)

有人能告诉我上面代码中的错误是什么吗?

小智 9

您可以使用QSignalMapper.虽然QSignalMapper是你问题的答案,但我认为jon hanson的回答是你应该采取的方式.你可以通过这种方式获得更清晰的代码.


Nol*_*Amy 8

四种方法.一个人不好意思.

  1. QSignalMapper.工作,但使代码混乱.
  2. 命名插槽.对于任何大量发件人而言都是乱码的,并且不适用于动态生成的发件人(例如,列表中的按钮).
  3. sender()-相比.可以处理动态发件人,但仍然有点难看.
  4. 对发件人进行子类化.不好意思.给你一直想要的东西:参数化信号.

特别是当您使用少量信号和发送方类型以及动态生成发件人时,将发件人子类化是最干净的方式.这使您可以重载现有信号以包含所需的任何参数.

现在,连接信号和插槽就可以了:

Keypad::Keypad(QWidget *parent) : QWidget(parent)
{
    for (int i = 0; i < 10; ++i)
    {
        // KeypadButton keeps track of the identifier you give it
        buttons[i] = new KeypadButton(i, this);
        // And passes it as a signal parameter. Booyah.
        connect(buttons[i], SIGNAL(clicked(int)), this, SIGNAL(digitClicked(int)));
    }
    createLayout();
}

void Keypad::digitClicked(int digit)
{
    // The slot can find the clicked button with ease:
    dial(button[i]); // or whatever
    //...
}
Run Code Online (Sandbox Code Playgroud)

并且额外的代码在子类中是不可见的,你永远不会再触摸它.

有关子类化的示例实现,请参阅http://doc.qt.digia.com/qq/qq10-signalmapper.html#thesubclassapproachQPushButton以发出clicked(int)信号.还讨论了所有四种方法 - 命名槽("普通解决方案"),sender(),子类化和信号映射器.

警告:显然最适合少量的发件人类型.但通常情况就是如此.在那种情况下,这是值得的.


jon*_*son 5

使用单独的插槽有什么效率低?如果插槽处理程序中存在共性,则将其移动到函数中,例如扩展ereOn的示例:

void YourClass::YourClass() :
  m_button1(new QPushButton()),
  m_button2(new QPushButton())
{
  connect(m_button1, SIGNAL(clicked()), this, SLOT(yourSlot1()));
  connect(m_button2, SIGNAL(clicked()), this, SLOT(yourSlot2()));
}

void YourClass::common(int n)
{
}

void YourClass::yourSlot1()
{
    common (1);
}

void YourClass::yourSlot2()
{
    common (2);
}
Run Code Online (Sandbox Code Playgroud)


ere*_*eOn 4

您不能传递常量,connect()因为有效参数是在执行时而不是编译时推导的。

然而,虽然这违反了OO原则,但您可以使用QObject::sender()which给出指向发射器的指针QObject

下面的例子:

void YourClass::YourClass() :
  m_button1(new QPushButton()),
  m_button2(new QPushButton())
{
  connect(m_button1, SIGNAL(clicked()), this, SLOT(yourSlot()));
  connect(m_button2, SIGNAL(clicked()), this, SLOT(yourSlot()));
}

void YourClass::yourSlot()
{
  if ((QPushButton* button = dynamic_cast<QPushButton*>(sender()))
  {
    // Now button points to a QPushButton* that you can compare with the pointers you already have

    if (button == m_button1)
    {
      // Whatever
    } else
    if (button == m_button2)
    {
      // Whatever
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

如果您有很多按钮,您还可以通过为每个按钮提供标识符来使用QSignalMapper 。