[英]How to subclass QPushButton so that the signal sends an argument to the slot?
I'm programming a little calculator in C++/Qt, and I'd like to avoid writing as much slots as there are QPushButton. 我正在用C ++ / Qt编写一个小计算器,并且我想避免编写与QPushButton一样多的插槽。 My teacher suggested me to subclass QPushButton and create a new signal. 我的老师建议我将QPushButton子类化并创建一个新信号。 So far I've written that : 到目前为止,我已经写过:
buttoncalc.h : buttoncalc.h:
class ButtonCalc : public QPushButton{
public:
ButtonCalc(QString string);
signals:
void sendValue(char c);
};
But I don't know what to do with that. 但是我不知道该怎么办。 I should first change the char emmited depending on the string I pass in the constructor but I don't know where I should do it in my code. 我首先应该根据在构造函数中传递的字符串来更改所发出的char,但是我不知道在代码中应该在哪里执行。 Should I also redefine the clicked() signal of QPushButton ? 我还应该重新定义QPushButton的clicked()信号吗?
I'm a little lost here so I thank you for your answers. 我在这里有点迷路,非常感谢您的回答。
EDIT (some precisions) : The ButtonClass is used as replacement of QPushButton in the class that draws the calculator. 编辑(有些精度):ButtonClass用作替换绘制计算器的类中的QPushButton。 I need a way to use a single slot in that class. 我需要一种在该类中使用单个插槽的方法。 This slot should therefore have a way to know which button has been clicked. 因此,该插槽应具有一种方法来知道单击了哪个按钮。
Actually, I intended to make a small sample which should show how to overload QPushButton
. 实际上,我打算制作一个小示例,该示例应显示如何重载QPushButton
。 But then I realized it is even simpler without overloading but using lambdas for the signal handler (which are supported since Qt5): 但是后来我意识到,在没有重载的情况下使用lambda作为信号处理程序(从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. 我访问了lbls
数组两次-一次访问QPushButton
标签,再次访问各自的信号处理程序。 Instead, I could have used the QPushButton
label itself for the latter. 相反,我本可以为后者使用QPushButton
标签本身。 (It's a matter of taste.) (这是一个品味问题。)
The lambda for the signal handler "binds" all specific info for the individual buttons in its environment: 信号处理程序的lambda“绑定”环境中各个按钮的所有特定信息:
qTxt
对qTxt
的引用 lbls
array 对lbls
数组的引用 i
and j
for array access. 用于数组访问的i
和j
的值。 The signature of the lambda has to match the one of the QPushButton::clicked
signal hence no parameters. Lambda的签名必须与QPushButton::clicked
信号之一匹配,因此没有参数。 The return type is actually missing but in this case, the C++ compile infers it from the return expression. 返回类型实际上是丢失的,但是在这种情况下,C ++编译器从返回表达式中推断出它。 Actually, their is no return
statement. 实际上,他们没有return
声明。 So, return type void
is inferred matching the QPushButton::clicked
signal signature as well. 因此,推断返回类型void
也与QPushButton::clicked
信号签名相匹配。
IMHO, lambdas and signal handlers are fitting together like (hopefully) your left and right shoe. 恕我直言,lambda和信号处理程序像(希望)您的左右鞋子一样装配在一起。 Signal/slots (I used sigc++ in the past) provided the concept of adapters needed for binding and hiding arguments or return values. 信号/插槽(我过去使用sigc ++)提供了绑定和隐藏参数或返回值所需的适配器的概念。 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. 由于lambda可以提供任何适配器,因此所有这些问题都已消除。
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. 我看到的lambda的唯一困难(除了语法之外):您必须仔细考虑环境(方括号[]
)中引用(或指向)变量的生存期。 (A lambda is not a closure - it may not extend the lifetime of its environment according to its own.) (lambda不是闭包,它可能无法根据自身的情况延长其生存期。)
Compiled and tested with VS2013, Qt5.6 on Windows 10 (64 bit): 已在Windows 10(64位)上使用VS2013,Qt5.6进行编译和测试:
Use QSignalMapper
which is designed for exactly this use case. 使用专门用于此用例的QSignalMapper
。 The documentation includes the example so I will not repeat it here: 该文档包含该示例,因此在此不再赘述:
http://doc.qt.io/qt-5/qsignalmapper.html http://doc.qt.io/qt-5/qsignalmapper.html
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.