当对话框中的任何小部件发出信号时,是否可以调用插槽



我正在尝试为应用程序创建一个配置菜单框,并使用QDialog框来显示用户可以更改的选项。该框包含QCOMBOBOXES和QLINEEDITS,但其中很多(7个组合框和12行编辑(。底部有一个qpushbutton,称为"应用更改",只有在更改框中的任何属性时才能启用。

我是否必须将每个小部件的每个信号与插槽链接到单独启用按钮,或者有一个信号表明Qdialog盒本身在其组成窗口上有更改时会发出?

现在我有一个:

connect(Combo1,SIGNAL(activated(QString)),this,SLOT(fnEnable(QString)));
connect(Combo2,SIGNAL(activated(QString)),this,SLOT(fnEnable(QString)))

随后还有17行这些连接。

void MyClass::fnEnable(QString)
{
ApplyButton->setEnabled(true); //It is initialised as false
}

我想知道这样做的方法是否较短,也许(就像我之前提到的(Qdialog发出的信号(我在文档中找不到一个(

我知道这不会加快程序的速度,因为只有所需的连接,但它会进一步尝试使更雄心勃勃的对话框更容易。

实际上没有这样的信号,但是一种方法是创建QComboBox的列表,并与A进行连接,例如:

QList <*QCombobox> l; 
l<<combobox1<< combobox2<< ....; 
for (auto combo: l) {
    connect(combo, &QComboBox::activated, this, &MyClass::fnEnable);
}

使用QLineEdit也可以完成。

您可以在窗口框的初始化列表上迭代并利用C 11为您完成所有无聊的工作:

MyClass::MyClass(QWidget * parent) : QWidget(parent) {
  auto const comboBoxes = {Combo1, Combo2, ... };
  for (auto combo : comboBoxes)
    connect(combo, &QComboBox::activates, this, &MyClass::fnEnable);
}

您也可以自动找到所有组合框:

MyClass::MyClass(QWidget * parent) : QWidget(parent) {
  ui.setupUi(this); // or other setup code
  for (auto combo : findChildren<QComboBox*>(this))
    connect(combo, &QComboBox::activated, this, &MyClass::fnEnable);
}

或者您可以自动连接到用户属性的更改信号。这将适用于具有用户属性的所有控件。用户属性是包含控件显示的主要数据的控件的属性。

void for_layout_widgets(QLayout * layout, const std::function<void(QWidget*)> & fun, 
                        const std::function<bool(QWidget*)> & pred = +[](QWidget*){ return true; })
{
  if (!layout) return;
  for (int i = 0; i < layout->count(); ++i) {
    auto item = layout->itemAt(i);
    for_layout_widgets(item->layout(), fun, pred);
    auto widget = item->widget();
    if (widget && pred(widget)) fun(widget);
  }
}
class MyClass : public QWidget {
  Q_OBJECT
  Q_SLOT void MyClass::fnEnable(); // must take no arguments
  ...
};
MyClass::MyClass(QWidget * parent) : QWidget(parent) {
  // setup code here
  auto slot = metaObject()->method(metaObject()->indexOfMethod("fnEnable()"));
  Q_ASSERT(slot.isValid());
  for_layout_widgets(layout(), [=](QWidget * widget){
    auto mo = widget->metaObject();
    auto user = mo->userProperty();
    if (!user.isValid()) return;
    auto notify = user.notifySignal();
    if (!notify.isValid()) return;
    connect(widget, notify, this, slot);
  });
}   

您还可以按值将组合框放在数组中。这可以最大程度地减少间接参考的成本和代码的结果,从而使记忆量最少并表现良好:

class MyClass : public QWidget {
  Q_OBJECT
  QVBoxLayout m_layout{this};
  std::array<QComboBox, 14> m_comboBoxes;
  ...
};
MyClass(QWidget * parent) : QWidget(parent) {
  for (auto & combo : m_comboBoxes) {
    m_layout.addWidget(&combo);
    connect(&combo, &QComboBox::activates, this, &MyClass::fnEnable);
  }
}

最新更新