Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Wait for a signal which carrying a specific argument
Qt 6.11 is out! See what's new in the release blog

Wait for a signal which carrying a specific argument

Scheduled Pinned Locked Moved Unsolved General and Desktop
2 Posts 2 Posters 476 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Q Offline
    Q Offline
    qiangxinglin
    wrote on last edited by
    #1

    Suppose we want wait a signal (with arguments), and keep blocking until meet an incoming signal carrying some specific arg?
    signals: triggered(int i)

    QTimer timer;
    timer.setSingleShot(true);
    QEventLoop loop;
    connect( this, &MyClass::triggered, &loop, [&](int i) {
        // only 123 would stop the event loop, otherwise keep waiting
        if (i == 123)  
            loop.quit();
    } );
    connect( &timer, &QTimer::timeout, &loop, &QEventLoop::quit );
    timer.start(msTimeout);
    loop.exec();
    
    if(timer.isActive())
        qDebug("Got 123! It may not be carried by the first incoming signal.");
    else
        qDebug("timeout");
    

    Is it possible to rewrite this into a reuseable header template? e.g.waitForTimeout(QObject* sender, Func1 signal, Func2 predicate, int msec)

    1 Reply Last reply
    0
    • SGaistS SGaist moved this topic from Wiki Discussion on
    • S Offline
      S Offline
      SimonSchroeder
      wrote on last edited by
      #2

      Most likely not.

      It is certainly possible to write a template template <class Func1, class Func2> void waitForTimeout(QObject* sender, Func1 signal, Func2 predicate, int msec) and call it with waitForTimeout(this, &MyClass::triggered, [&](int i){...}, msTimeout);.

      However, the predicate cannot reference the loop because it cannot capture it. Possibly there is a workaround that you could also provide an additional signal which will be connected to loop.quit(). This signal could be captured by your predicate lambda and thus emitted.

      Another approach could be to make it a class waitForTimeout_t. Then I would probably store the predicate as a std::function. This would allow a 2-step approach with a constructor and member functions:

      waitForTimeout_t waiter(this, &MyClass::triggered, [&](int i) {}, msTimeout); // just a dummy lambda to get the type right for std::function
      waiter.setPrecidate([&](int i) { if(i == 123) waiter.getLoop().quit(); });
      waiter.wait();
      

      In simple cases you could directly write:

      waitForTimeout_t(this, &MyClass::triggered, [&](int i) {...}, msTimeout).wait();
      

      It would be little annoying to always have to write wait(), though.

      One other disadvantage would be that I would assume that the last few lines (if(time.isActive())...) would be per specific use cases. With my first suggestion the template function waitForTimeout(...) could just return a bool which tells you if the timer did fire.

      The thing is that this approach should not be your goto solution. Nested loops are considered evil in Qt. Nothing is preventing you from becoming deeply nested. Qt documentation itself discourages using nested loops. They should be rarely used. Thus, it is best to not write a template for this because it would encourage using this approach.

      1 Reply Last reply
      1

      • Login

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved