Qt QSignalMapper 正在为地图中的每个项目发出信号

Qt QSignalMapper is emitting a signal for every item in the map

我有一个函数可以接收我创建的 class 的 QList。我们称这个假设为 class "Stuff"。所以,这个函数接收到一个 QList of Stuff

我遍历 QList,根据 "Stuff" 对象的属性,我将生成以下内容之一:

1) QLineEdit

2) QCheckBox

3) QComboBox

这不是实际的代码,但我实际上是这样做的:

void MyProgram::update(QList<Stuff> myStuffs)
{
  this->mSignalMapper = new QSignalMapper();

  foreach (Stuff stuff, myStuffs)
  {
    if (stuff.isInt())
    {
      QLineEdit* input = new QLineEdit();
      //There is code here to setup the QLineEdit and fill an initial value
      verticalLayout->addWidget(input); //verticalLayout is QVBoxLayout
      QObject::connect(input, SIGNAL(editingFinished()), this->mSignalMapper, SLOT(map()));
      this->mSignalMapper->setMapping(input, stuff.getMappingId());
      /*
       * NOTE: the stuff.getMappingId() function returns an int that is unique
       * to that stuff object.  I'm 100% sure each stuff object is getting
       * a unique mapping ID */
      QObject::connect(this->mSignalMapper, SIGNAL(mapped(int)), this, SLOT(onStuffChanged(int)));
    }
    else if (stuff.isBool())
    {
      QCheckBox* input = new QCheckBox();
      //There is code here to setup the QCheckBox and set an initial value
      verticalLayout->addWidget(input);
      QObject::connect(input, SIGNAL(stateChanged(int)), this->mSignalMapper, SLOT(map()));
      this->mSignalMapper->setMapping(input, stuff.getMappingId());
      QObject::connect(this->mSignalMapper, SIGNAL(mapped(int)), this, SLOT(onStuffChanged(int)));
    }
    else if (stuff.isStringList())
    {
      QComboBox* input = new QComboBox();
      //There is code here to setup the QComboBox and fill in values for the combo box
      verticalLayout->addWidget(input);
      QObject::connect(input, SIGNAL(activated(int)), this->mSignalMapper, SLOT(map()));
      this->mSignalMapper->setMapping(input, stuff.getMappingId());
      QObject::connect(this->mSignalMapper, SIGNAL(mapped(int)), this, SLOT(onStuffChanged(int)));
    }
  }
}

问题是,如果我通过编辑 QLineEdit、选中复选框或更改组合框值来触发 Widget 的信号之一,onStuffChanged(int) 函数将被调用 N 次,其中 N = mSignalMapper 映射的数量。

这是怎么回事?如果我遍历并创建 10 个小部件,则仅单击 10 个小部件中的 1 个会调用该函数 10 次,而这 10 次中的每一次都会传递与我交互的 1 个对象关联的唯一 int。因此,如果 10 个小部件中的第一个是唯一 int ID 为 27 的复选框,则 onStuffChanged(int) 函数将被调用 10 次,每次调用参数为 27。

问题出在这一行:

QObject::connect(this->mSignalMapper, SIGNAL(mapped(int)), this, SLOT(onStuffChanged(int)));

您正在建立相同的连接 N 次(N = 您的 "stuff" 计数),因此每一个 mapped() 信号也会触发 onStuffChanged(int) 插槽 N 次。

解法: 将此行移到循环外,只调用一次。