我用C ++ / Qt编写了一个小计算器,我想避免像QPushButton一样编写多少个插槽。 我的老师建议我继承QPushButton并创建一个新信号。 到目前为止,我已写过:
buttoncalc.h:
class ButtonCalc : public QPushButton{
public:
ButtonCalc(QString string);
signals:
void sendValue(char c);
};
但我不知道该怎么做。我应该首先根据我在构造函数中传递的字符串更改char,但我不知道在代码中应该在哪里执行。我还应该重新定义QPushButton的clicked()信号吗?
我有点迷失在这里,所以我感谢你的答案。
编辑(一些精确): ButtonClass用于替换绘制计算器的类中的QPushButton。 我需要一种方法来使用该类中的单个插槽。因此,此插槽应该可以知道单击了哪个按钮。答案 0 :(得分:1)
实际上,我打算制作一个小样本,该样本应该显示如何重载QPushButton
。但后来我意识到它更简单,没有重载但是使用lambdas作为信号处理程序(从Qt5开始支持):
// standard C++ header:
#include <iostream>
// Qt header:
#include <QApplication>
#include <QGridLayout>
#include <QGroupBox>
#include <QLineEdit>
#include <QMainWindow>
#include <QPushButton>
using namespace std;
int main(int argc, char **argv)
{
cout << QT_VERSION_STR << endl;
// main application
#undef qApp // undef macro qApp out of the way
QApplication qApp(argc, argv);
// setup GUI
QMainWindow qWin;
QGroupBox qBox;
QGridLayout qGrid;
QLineEdit qTxt;
qGrid.addWidget(&qTxt, 0, 0, 1, 4);
enum { nCols = 4, nRows = 4 };
QPushButton *pQBtns[nRows][nCols];
const char *lbls[nRows][nCols] = {
{ "7", "8", "9", "-" },
{ "4", "5", "6", "+" },
{ "1", "2", "3", "*" },
{ "0", ".", "=", "/" },
};
for (int i = 0; i < nRows; ++i) {
for (int j = 0; j < nCols; ++j) {
pQBtns[i][j]
= new QPushButton(QString::fromLatin1(lbls[i][j]), &qWin);
qGrid.addWidget(pQBtns[i][j], i + 1, j);
}
}
qBox.setLayout(&qGrid);
qWin.setCentralWidget(&qBox);
qWin.show();
// install signal handlers
for (int i = 0; i < nRows; ++i) {
for (int j = 0; j < nCols; ++j) {
QObject::connect(pQBtns[i][j], &QPushButton::clicked,
// easy done with a lambda:
[&qTxt, &lbls, i, j]() {
qTxt.setText(qTxt.text() + QString::fromLatin1(lbls[i][j]));
});
}
}
// run application
return qApp.exec();
}
注意:
各个按钮的具体信息实际上绑定到信号处理程序本身(而不是使其成为派生类的成员)。
我访问了lbls
数组两次 - 一次用于QPushButton
标签,再次用于相应的信号处理程序。相反,我可以为后者使用QPushButton
标签本身。 (这是品味问题。)
信号处理程序的lambda&#34;绑定&#34;其环境中各个按钮的所有特定信息:
qTxt
lbls
数组i
和j
的值。 lambda的签名必须与QPushButton::clicked
信号匹配,因此没有参数。实际上缺少返回类型,但在这种情况下,C ++编译从返回表达式中推断出它。实际上,他们不是return
陈述。因此,推断返回类型void
也与QPushButton::clicked
信号签名相匹配。
恕我直言,lambdas和信号处理程序像(希望)你的左右鞋一样装配在一起。 Signal / slots(我过去使用过sigc ++)提供了绑定和隐藏参数或返回值所需的适配器概念。它工作,但每次我不得不使用它我努力寻找正确的嵌套 - 这是一个烂摊子。由于lambda可以提供任何适配器,所有这些问题都消失了。
我看到lambda的唯一困难(除了语法):你必须仔细考虑环境中引用(或指向)变量的生命周期(括号[]
中的事物)。 (lambda不是一个闭包 - 它可能不根据它自己延长其环境的生命周期。)
在Windows 10(64位)上使用VS2013,Qt5.6进行编译和测试:
答案 1 :(得分:1)
使用专为此用例设计的QSignalMapper
。文档包含示例,因此我不在此重复: