Qt 5 将带有参数的插槽分配给 QPushButton
Posted
技术标签:
【中文标题】Qt 5 将带有参数的插槽分配给 QPushButton【英文标题】:Qt 5 assign slot with parameters to a QPushButton 【发布时间】:2014-01-16 00:03:23 【问题描述】:我有一个 C++ 上的 Qt 应用程序,我想为 QPushButton 分配一个插槽。但我想传递一些参数,因为我有不止一个 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)));
这是在两个嵌套循环中完成的,因此 i
和 j
定义明确。
我的错误是:
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
是一个宏,它将函数 signature 封装在要传递给 connect
的字符串中。
所以应该是handleButton(int,int)
?!但是我该如何传递参数呢?!
【参考方案1】:
遗憾的是,当调用信号时,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 非常易读.
【讨论】:
非常感谢!我可以用简单的公式i*count_on_row + j
减少到一个,所以我会尝试第一种方法,我希望它会起作用!非常感谢您的详细回答:)
很高兴能帮上忙。我添加了第三种方法,如果你有 Qt5,这很好。请注意,如果您只需要这些值来访问您的按钮数组以获取按钮指针,您也可以简单地使用 sender()
并完成。
哦,他们添加了 lambda!伟大的!这非常有效!非常感谢! :)以上是关于Qt 5 将带有参数的插槽分配给 QPushButton的主要内容,如果未能解决你的问题,请参考以下文章
Qt - 使用 lambda 函数修改先前连接信号的插槽参数