Qt 5如何将带参数的slot分配给QPushButton?

10

我有一个用C++编写的Qt应用程序,我想要为QPushButton分配一个槽(slot)。但是我想要传递一些参数,因为我有多个QPushButton执行类似的操作,所以我想要一个带有参数的函数,但是Qt不停地告诉我没有这样的槽位。有人能告诉我为什么以及应该如何做吗?

提前致谢。

在.h文件中我有:(一开始它是私有的,但我在寻找问题时进行了更改)

public slots:
    void handleButton(int row, int col);

接着在.cpp文件中:

void fieldWindow::handleButton(int row, int col){
    cout << row << " " << col << endl;
}

同样在同一个 .cpp 文件中再次出现:

connect(this->buttonsField[i][j], SIGNAL(released()), this, SLOT(handleButton(i,j)));

这是在两个嵌套循环中完成的,因此 ij 都有明确定义。

我的错误是:

QObject::connect: No such slot fieldWindow::handleButton(i,j) in ..\Proj1\fieldwindow.cpp:41
QObject::connect:  (receiver name: 'fieldWindow')

我在互联网上读到说我应该写 handleButton(int, int);,但是接下来我该如何传递参数呢?


connect语句在SIGNAL(...)表达式中不接受任何参数。SIGNAL是一个宏,它将函数签名封装在一个字符串中,以便传递给connect - leemes
所以应该是 handleButton(int,int) ?!但我怎么传递参数呢?! - Bankin
1个回答

15

可悲的是,Qt信号槽连接在信号被调用时不接受传递到槽中的任何参数。这仅在信号本身提供这些参数时才起作用,但你不能在connect语句中添加它们。

但你并不是唯一想要做这件事情的人,因此在Qt中有一个类几乎可以满足你的需求:QSignalMapper。该类的实例可用作信号槽连接的“代理”:将(多个)按钮连接到该类的槽,并将该类的信号连接到目标槽。然后,对于每个“发送者”实例(在你的情况下是按钮),你可以告诉该类要添加哪个值到调用的槽中。例如:

QPushButton * button1 = ...;
QPushButton * button2 = ...;

QSignalMapper mapper;

connect(button1, SIGNAL(released()), &mapper, SLOT(map()));
mapper.setMapping(button1, 42); // Number to be passed in the slot

connect(button2, SIGNAL(released()), &mapper, SLOT(map()));
mapper.setMapping(button2, 1337); // Number to be passed in the slot

connect(&mapper, SIGNAL(mapped(int)), this, SLOT(handleButton(int)));

很遗憾,正如您所看到的,这个类只能处理一个参数。对于您的情况,您应该选择另一种方法(我之前解释过,以防您再次遇到类似但仅有一个int参数的问题)。

适合您问题的替代方案是在插槽内依赖sender()。记住将您的映射存储在像数据结构中:

QMap<QObject*,int> rows;
QMap<QObject*,int> cols;

并且访问那些在你的插槽中不需要参数的内容

void fieldWindow::handleButton(){
    int row = rows[sender()];
    int col = cols[sender()];
    cout << row << " " << col << endl;
}

当初始化您的UI时,您需要在这些映射中放置适当的值。或者您可以在现有数组buttonsField中搜索按钮。

自Qt5和C++11以来存在另一种方法:您可以在lambda函数中处理信号,而不是使用槽函数。这将看起来像这样(信号使用新语法命名):

connect(this->buttonsField[i][j], &QPushButton::released, [=]{
    handleButton(i, j);
});
如果您不喜欢lambda语法,也可以使用标准库中的一些辅助函数来组合一个函子而不是lambda,或者编写自己的函子类,但我个人认为lambda很容易阅读。
如果您不喜欢lambda语法,还有其他方式可以使用标准库中的一些辅助函数来组合一个函子,或者编写自己的函子类。但是我个人认为lambda非常容易阅读。

非常感谢!我可以用简单的公式i*count_on_row + j将其缩减为一个,所以我会尝试第一种方法,希望它能够奏效!非常感谢您详细的回答 :) - Bankin
2
我很高兴能够帮忙。我添加了第三种方法,如果你有Qt5的话会很好用。请注意,如果你只需要这些值来访问你的按钮数组以获取按钮指针,则也可以简单地使用“sender()”,然后完成了。 - leemes
3
哦,他们添加了Lambda!太棒了!这正好起作用!非常感谢你! :) - Bankin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接