如何将参数从构造函数传递到插槽?

时间:2016-08-12 07:42:46

标签: c++ qt signals-slots

我正在和Qt做一个小练习。据我所知,插槽save_clicked只带来参数类型。那么如何将userid转移到文件save_clicked中的广告位MyClass.cpp进行处理呢?

MyClass.h

class MyClass : public QWidget
{
    Q_OBJECT

public:
    MyClass(QString userid, QString lastname, QString firstname, QWidget *parent = 0);
    ~MyClass();

public slots:
    void save_clicked(QString userid);

private:
    Ui::MyClass ui;
};

#endif // MYCLASS_H

MyClass.cpp

MyClass::MyClass(QString userid, QString lastname, QString firstname, QWidget *parent)
: QWidget(parent)
{
    ui.setupUi(this);
    ...........
    ...........
    connect(ui.save, SIGNAL(clicked()), this, SLOT(save_clicked(QString)));
}

void MyClass::save_clicked(QString userid)
{
    // process userid here    
}

2 个答案:

答案 0 :(得分:2)

首先,已经有人建议userid不需要传递到插槽。将其声明为MyClass的成员,只需在MyClass::save_clicked()中使用它就可以了。

如果您仍然想知道如何处理需要将参数传递给信号未提供的插槽的情况,有多种方法可以实现这一点,它们取决于您使用的Qt版本。

一般来说,Qt5 docs的以下内容适用于Qt5和Qt4:

  

信号的签名必须与接收的签名相匹配   插槽。 (事实上​​,一个插槽的签名可能比它的信号更短   收到因为它可以忽略额外的参数。)

鉴于这一事实,您必须使用信号提供的信息(或者不使用 - 取决于您是否需要它)或将数据提供给其他地方。 slot只是一个常规函数(在Qt4中稍微受限制,但在Qt5中,你基本上可以将任何可调用的连接到一个信号)并且在该函数中,你可以得到数据你需要从你的设计允许的任何地方。成员变量方法很常见,但您也可以调用任何其他对象的另一个成员函数,自由函数或简单地计算插槽内所需的任何内容。

注意:处理信号并不一定意味着你需要任何数据 - 这是常见的,是的,但你也可以做一些简单的事情,因为提出QMessageBox有一些困难编码文本或简单地清除一些文本编辑(想象某个按钮执行Clear Console)或执行一些外部过程或你有什么。

如果您在调用时需要插槽实际接收数据,则有多种选择:

  • 使用信号提供的所有内容或子集
  • 使用QSignalMapper建立一个对插槽参数的控制有限的映射
  • 使用恕我直言,使用存储所需内容的函数对象的优越方法,即直接提供的函子或作为lambda或从std::bind返回的函数对象

对于后者工作,您需要C++11支持,但到现在为止,这应该不是问题。

在上面的示例中,您可以使用最基本的方法执行此类操作( UNTESTED - 请报告编译错误,以便我可以解决问题):

MyClass::MyClass(QString userid, QString lastname, QString firstname, QWidget *parent)
: QWidget(parent)
{
  ...

  connect (
    ui.save, 
    &QPushButton::clicked, 
    std::bind (&MyClass::save_clicked, this, userid)
  );

  ...
}

在上述情况下,当clicked()发出ui.save时,std::bind返回的函数调用包装器将被调用,而MyClass::save_clicked将调用this { {1}} {1}}的实例,并将MyClass传递给userid

以上基本上是您最初想要实现的目标。然而,这只是冰山一角。你可以更进一步,更进一步,例如,绑定你想要的任何

例如,假设您已连接到按钮save_clicked()提供的另一个信号。如果您希望同时收到检查状态为bool 您自己提供的一些参数,例如toggled(bool checked),则可以将上述调用扩展为userid一个合适的占位符:

std::bind

您现在可以拥有connect ( ui.save, &QPushButton::toggled, std::bind (&MyClass::save_clicked, this, _1, userid /*, ... more args here*/) ); 的以下签名:

save_clicked()

save_clicked(bool, QString); 发出toggled(bool)后,ui.save返回的函数调用包装器将调用std::bind,同时使用bool代替MyClass::save_clicked < strong>和您提供的_1作为QString的第4个参数。

答案 1 :(得分:1)

优于使用信号/插槽只需使用变量。这是班级的目标。添加如下内容:

private:

QString userId;

在你的构造函数中添加:

MyClass::MyClass(QString userid, QString lastname, QString firstname, QWidget *parent)
: QWidget(parent)
{
    ui.setupUi(this);
    this.userId=userid;

}

像这样你可以像你想要的那样使用userId以及你想要进入你班级的地方。

编辑:

添加你的.h

private slots:
    void on_saveButton_clicked();

和你的.cpp

void MyClass::on_saveButton_clicked()
{
    // you can use userId here
}

如果您使用Qt Creator,这些功能可以在UI设计界面中自动添加