Qt - “没有这样的插槽”,虽然有

时间:2016-03-06 12:22:36

标签: c++ qt

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

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);

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

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)被调用? 谢谢!

3 个答案:

答案 0 :(得分:6)

您无法直接将值传递到Qt中的插槽,如SLOT(resizeGrid(3))中所示。 SLOT的参数应该只是方法的签名(resizeGrid())。

如何向插槽添加参数有两种方法。关于how to pass arguments to a slot的这个问题显示了一些解决方案,在此重复。 (去投票吧!)

现代方式:Qt5和C ++ 11

而不是连接广告位,请连接到仿函数,如Kuba Ober中的this answer所述:

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执行所需内容,如TonyKthis answer所述:

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))) ;

答案 1 :(得分:2)

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

例如,您可以将signal(int, float)slot(int)相关联,但无法将signal(void)slot(int)相关联。

如果您使用的是Qt 5,那么在连接语法中指定一个槽参数是“有可能的”:

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

当然,你可以在这种特殊情况下使用信号映射器,但它是一个相当笨拙的解决方案 - 额外的冗长,仅限于一个int,string,widget或QObject参数。对于lambdas,这些限制不适用。

答案 2 :(得分:1)

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

并且可能(在 vsimkus 的答案中的例子)在int n = 3中发送参数。您也可以通过信号参数在connect(...)部分发送它们。

Here是关于广告位和信号的好文章。