Actually, I intended to make a small sample which should show how to overload QPushButton
. But then I realized it is even simpler without overloading but using lambdas for the signal handler (which are supported since Qt5):
#include <QtWidgets>
int main(int argc, char **argv)
{
qDebug() << QT_VERSION_STR;
// main application
QApplication app(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 app.exec();
}
Notes:
The specific info for the individual buttons is actually bound to the signal handler itself (instead making it a member of the derived class).
I accessed the lbls
array twice - once for the QPushButton
label, again for the respective signal handler. Instead, I could have used the QPushButton
label itself for the latter. (It's a matter of taste.)
The lambda for the signal handler "binds" all specific info for the individual buttons in its environment:
- a reference to the
qTxt
- a reference to the
lbls
array
- the values of
i
and j
for array access.
The signature of the lambda has to match the one of the QPushButton::clicked
signal hence no parameters. The return type is actually missing but in this case, the C++ compile infers it from the return expression. Actually, their is no return
statement. So, return type void
is inferred matching the QPushButton::clicked
signal signature as well.
IMHO, lambdas and signal handlers are fitting together like (hopefully) your left and right shoe. Signal/slots (I used sigc++ in the past) provided the concept of adapters needed for binding and hiding arguments or return values. It worked but everytimes I had to use it I struggled in finding the correct nesting - it was a mess. All these problems are away since lambdas can provide any adapter.
The only difficulty with lambdas I see (beside of the syntax): you have to consider lifetimes of referenced (or pointed) variables in the environment (the thing in the brackets []
) carefully. (A lambda is not a closure - it may not extend the lifetime of its environment according to its own.)
Compiled and tested with VS2013, Qt5.6 on Windows 10 (64 bit):
