Qt - "No such slot" ,虽然有

Qt - "No such slot", although there is

本文关键字:such No Qt slot      更新时间:2023-10-16

我正在尝试将按钮连接到函数,因此当我按下按钮时,该函数会使用特定参数调用。我有

class FieldGridWidget : public QWidget
{
    Q_OBJECT
public:
    FieldGridWidget(QWidget *parent=0);
    ~FieldGridWidget();
public slots:
    void resizeGrid(int n);
private:
    QGridLayout* _gridLayout;
    QVector<QPushButton*> _buttonGrid;
};

然后按钮

_button3 = new QPushButton("3x3", this);

我正在尝试连接它,因此如果单击它,resizeGrid函数将使用参数 3 调用。为此,我正在尝试

connect(_button3, SIGNAL(clicked()), _fieldGrid, SLOT(resizeGrid(3))); //this is line 21

但是我收到运行时错误 QObject::connect: No such slot FieldGridWidget::resizeGrid(3) in ../filename.cpp:21

我做错了什么?或者我怎么能做到,如果我按下按钮,resizeGrid(3)被召唤?谢谢!

你不能像在 SLOT(resizeGrid(3)) 中那样直接将值传递给 Qt 中的插槽。SLOT的参数应该只是方法的签名(resizeGrid())。

有两种

方法可以向槽添加参数。这个关于如何将参数传递给插槽的问题展示了一些解决方案,在这里重复。(去投票吧!

现代方式:Qt5和C++11

与其连接插槽,不如连接到函子,正如 Kuba Ober 在此答案中所述:

connect(action1,  &QAction::triggered, this, [this]{ onStepIncreased(1); });
connect(action5,  &QAction::triggered, this, [this]{ onStepIncreased(5); });
connect(action10, &QAction::triggered, this, [this]{ onStepIncreased(10); });
connect(action25, &QAction::triggered, this, [this]{ onStepIncreased(25); });
connect(action50, &QAction::triggered, this, [this]{ onStepIncreased(50); });

老式的:QSignalMapper

您可以使用QSignalMapper来执行您想要的操作,如 TonyK 在此答案中所述:

QSignalMapper* signalMapper = new QSignalMapper (this) ;
connect (action1, SIGNAL(triggered()), signalMapper, SLOT(map())) ;
connect (action5, SIGNAL(triggered()), signalMapper, SLOT(map())) ;
connect (action10, SIGNAL(triggered()), signalMapper, SLOT(map())) ;
connect (action25, SIGNAL(triggered()), signalMapper, SLOT(map())) ;
connect (action50, SIGNAL(triggered()), signalMapper, SLOT(map())) ;
signalMapper -> setMapping (action1, 1) ;
signalMapper -> setMapping (action5, 5) ;
signalMapper -> setMapping (action10, 10) ;
signalMapper -> setMapping (action25, 25) ;
signalMapper -> setMapping (action50, 50) ;
connect (signalMapper, SIGNAL(mapped(int)), this, SLOT(resizeGrid(int))) ;

信号和插槽的签名必须匹配 - 如果不是完全匹配,那么至少部分匹配。

例如,您可以将signal(int, float)连接到slot(int),但不能将signal(void)连接到slot(int)

在连接语法中指定插槽参数是"可能的",前提是您使用的是Qt 5:

connect(_button3, &QPushButton::clicked, [=](){ _fieldGrid->resizeGrid(3); }); 

当然,您可以在这种特殊情况下使用信号映射器,但这是一个相当笨拙的解决方案 - 非常冗长,并且仅限于单个整数、字符串、小部件或QObject参数。对于 lambda,这些限制不适用。

clicked()resizeGrid()签名应该相同,因此您可以创建函数,例如,resizeGridForButton()resizeGrid(3)将被执行,或者更改resizeGrid()签名并将int n = 3传输到其中。

并且

不可能vsimkus 答案中的示例)在 connect(...) 中发送参数.您也可以通过信号参数将它们分成emit部分发送。

这是一篇关于老虎机和信号的好文章。