对象组
Group of objects
在我的 Qt5 程序中,我正在处理多个对象,需要花费大量时间和代码来禁用或更改 20 个复选框的状态。是否有任何选项可以制作一组复选框(或任何其他对象)并用一行对其执行命令?
例如:
QCheckBox b1, b2, b3, b4, b5;
QCheckBox_Group Box_1to5 = {b1, b2, b3, b4, b5};
ui->Box_1to5->setEnabled(false);
可以吗?
Frank 的评论正是您想要的 enabling/disabling 一组小部件,但我将回答您关于如何将状态更改应用于一组对象的更一般的问题。如果您可以自由使用 C++11,那么以下内容将使您具备使用一组通用函数参数调用任何对象上的任何成员函数的一般能力:
// Member functions without arguments
template<typename ObjectPtrs, typename Func>
void batchApply(ObjectPtrs objects, Func func)
{
for (auto object : objects)
{
(object->*func)();
}
}
// Member functions with 1 or more arguments
template<typename ObjectPtrs, typename Func, typename ... Args>
void batchApply(ObjectPtrs objects, Func func, Args ... args)
{
for (auto object : objects)
{
(object->*func)(args ...);
}
}
通过以上内容,您可以实现使用一行代码调用一组对象上的函数的目标。你会像这样使用它:
QCheckbox b1, b2, b3, b4, b5;
auto Box_1to5 = {b1, b2, b3, b4, b5};
batchApply(Box_1to5, &QCheckbox::setChecked, false);
batchApply(Box_1to5, &QCheckbox::toggle);
上述方法的一个限制是它不处理默认函数参数,因此即使函数有默认参数,您也必须明确提供一个。例如,以下将导致编译器错误,因为 animateClick
有一个参数(忽略其默认值):
batchApply(Box_1to5, &QCheckbox::animateClick);
上述技术使用 可变参数模板 来支持任意数量和类型的函数参数。如果您还不熟悉这些,您可能会发现以下内容很有用:
https://crascit.com/2015/03/21/practical-uses-for-variadic-templates/
您可以定义一个信号并将其连接到所有复选框:
/* In the constructor or at the start*/
QVector<QCheckbox*> boxes{b1, b2, b3, b4, b5};
for(QCheckbox* box: boxes) {
connect(this, &MyWidget::setBoxCheckedState, box, &QCheckbox::setChecked);
}
/* Somewhere in the code where the state should change */
emit setBoxCheckedState(true); // <- custom signal on your class
或者您可以使用 for_each 算法:
bool checked = true;
std::for_each(boxes.begin(), boxes.end(), [checked](QCheckbox* box) {
box->setChecked(checked);
});
在我的 Qt5 程序中,我正在处理多个对象,需要花费大量时间和代码来禁用或更改 20 个复选框的状态。是否有任何选项可以制作一组复选框(或任何其他对象)并用一行对其执行命令?
例如:
QCheckBox b1, b2, b3, b4, b5;
QCheckBox_Group Box_1to5 = {b1, b2, b3, b4, b5};
ui->Box_1to5->setEnabled(false);
可以吗?
Frank 的评论正是您想要的 enabling/disabling 一组小部件,但我将回答您关于如何将状态更改应用于一组对象的更一般的问题。如果您可以自由使用 C++11,那么以下内容将使您具备使用一组通用函数参数调用任何对象上的任何成员函数的一般能力:
// Member functions without arguments
template<typename ObjectPtrs, typename Func>
void batchApply(ObjectPtrs objects, Func func)
{
for (auto object : objects)
{
(object->*func)();
}
}
// Member functions with 1 or more arguments
template<typename ObjectPtrs, typename Func, typename ... Args>
void batchApply(ObjectPtrs objects, Func func, Args ... args)
{
for (auto object : objects)
{
(object->*func)(args ...);
}
}
通过以上内容,您可以实现使用一行代码调用一组对象上的函数的目标。你会像这样使用它:
QCheckbox b1, b2, b3, b4, b5;
auto Box_1to5 = {b1, b2, b3, b4, b5};
batchApply(Box_1to5, &QCheckbox::setChecked, false);
batchApply(Box_1to5, &QCheckbox::toggle);
上述方法的一个限制是它不处理默认函数参数,因此即使函数有默认参数,您也必须明确提供一个。例如,以下将导致编译器错误,因为 animateClick
有一个参数(忽略其默认值):
batchApply(Box_1to5, &QCheckbox::animateClick);
上述技术使用 可变参数模板 来支持任意数量和类型的函数参数。如果您还不熟悉这些,您可能会发现以下内容很有用:
https://crascit.com/2015/03/21/practical-uses-for-variadic-templates/
您可以定义一个信号并将其连接到所有复选框:
/* In the constructor or at the start*/
QVector<QCheckbox*> boxes{b1, b2, b3, b4, b5};
for(QCheckbox* box: boxes) {
connect(this, &MyWidget::setBoxCheckedState, box, &QCheckbox::setChecked);
}
/* Somewhere in the code where the state should change */
emit setBoxCheckedState(true); // <- custom signal on your class
或者您可以使用 for_each 算法:
bool checked = true;
std::for_each(boxes.begin(), boxes.end(), [checked](QCheckbox* box) {
box->setChecked(checked);
});