简体   繁体   中英

Connect a Qt signal to a slot using std::bind

I have many QActions and I would like to connect their triggered(bool) signal to a specific slot which gets an integere number as input, let's say setX(int x) . I need to specify x in connect callback. For example:

connect(actionV, &QAction::triggered,
        this, &TheClass::setX /* somehow x=10 */);

I tried using std::bind and it does not work:

connect(actionV, &QAction::triggered,
        std::bind(this, &TheClass::setX, 10));

You can solve this easily using a lambda:

connect(actionV, &QAction::triggered, [&] { 
   m_theClass.setX(10);
});

The syntax you used for std::bind was incorrect, that's why it didn't compile.

While using a lambda is faster, I am going to post some examples using std::bind for completeness shake in the hope of being helpful to other programmers as well.

Example A:

// Declaration somewhere in a header file.
void setX(int x);

/*
 * In a cpp file:
 * Notice the order of the arguments. 
 * a) The pointer to the class member
 * b) the instance of the class (in this case is "this")
 * c) The arguments to the function are the rest.
 */
connect(actionV, &QAction::triggered, this, std::bind(&MyClass::setX, this, 10));

Now, let's pretend that you must capture the parameter of a signal . In this case it's a bool . I have to remind you, that the signature is void QAction::triggered(bool checked = false) .

Example B:

// Again, declaration in a header file.
void setX(bool c, int x);

/*
 * In a cpp file:
 * Notice how the emmited bool value is captured with
 * std::placeholders::_1 and then you pass 10 as well.
 */
connect(actionV,
        &QAction::triggered,
        this,
        std::bind(&MyClass::setX, this, std::placeholders::_1, 10));

To make this even more extreme, let's pretend once again that you have two overloads of setX .

Example C:

// Declaration in a header file
void setX(bool x, int x);
void setX(int x);

/*
 * In your .cpp file:
 * a) Choose the first signature
 * b) Choose the second signature
 */
connect(actionV,
        &QAction::triggered,
        this,
        std::bind(qOverload<bool, int>(&MyClass::setX),
                  this, std::placeholders::_1, 10));
// OR

connect(actionV,
        &QAction::triggered,
        this,
        std::bind(qOverload<int>(&MyClass::setX), this, 10));

But the qOverload macro needs at least a C++14 capable compiler though. You don't want to go to:

connect(actionV,
        &QAction::triggered,
        this,
        std::bind(static_cast<void(MyClass::*)(bool, int)>(&MyClass::setX),
                  this,
                  std::placeholders::_1,
                  10));

I hope I helped a bit to clarify the syntax. I can't stress enough though that using a lambda is more efficient and simple and that this was just a fun "exercise".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM