我正在尝试为应用程序创建一个配置菜单框,并使用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);
}
}