如何将参数从构造函数转移到槽中

How to transfer parameter from constructor into slot?

本文关键字:转移 构造函数 参数      更新时间:2023-10-16

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

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    
}

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

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

一般来说,Qt5文档中的下列内容适用于Qt5和Qt4:

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

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

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

如果您需要您的插槽在调用时实际接收数据,您有多个选项:

  • 使用信号提供的所有内容或子集
  • 使用QSignalMapper建立一个映射,对您的槽参数进行有限的控制
  • 使用更高级的方法,使用一个函数对象来存储你需要的东西,也就是说,要么是一个你直接提供的函子,要么是一个lambda或一个从std::bind
  • 返回的函数对象。

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

在上面的例子中,你可以用最基本的方法做这样的事情(未经测试的 -请报告编译错误,以便我可以修复答案):

MyClass::MyClass(QString userid, QString lastname, QString firstname, QWidget *parent)
: QWidget(parent)
{
  ...
  connect (
    ui.save, 
    &QPushButton::clicked, 
    std::bind (&MyClass::save_clicked, this, userid)
  );
  ...
}

在上面的例子中,当ui.save发出clicked()时,将调用std::bind返回的函数调用包装器,该包装器将在MyClassthis实例上调用MyClass::save_clicked,并将userid传递给save_clicked()

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

例如,假设您连接到按钮toggled(bool checked)提供的另一个信号。如果您希望同时接收作为bool 的检查状态(您自己提供的一些参数,例如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);

ui.save发出toggled(bool)时,std::bind返回的函数调用包装器将调用MyClass::save_clicked,并将bool值替换为_1 (作为std::bind的第四个参数提供的QString)。

使用变量比使用信号/插槽更好。这是一门课的目标。添加如下内容:

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设计界面