Results 1 to 4 of 4

Thread: One function in connect() and QTimer::singleShot()

  1. #1
    Join Date
    Sep 2021
    Posts
    3
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11

    Question One function in connect() and QTimer::singleShot()

    Hello!

    I'm very new to C++ (learning while writing this app). I do have some experience with QT using pyside2, but i want to write my app in C++.

    My current problem is calling one function with connect() AND QTimer::singleShot().

    some snippets of my code:

    mainwindow.h
    Qt Code:
    1. private slots: // in MainWindow class
    2. void searchTable(int searchID);
    To copy to clipboard, switch view to plain text mode 

    mainwindow.cpp
    Qt Code:
    1. #include "mainwindow.h"
    2. #include "systemdialog.h"
    3. #include "ui_MainWindow.h"
    4. #include "ui_SystemDialog.h"
    5. MainWindow::MainWindow(QWidget *parent):
    6. QMainWindow(parent),
    7. ui(new Ui::MainWindow)
    8. {
    9. ui->setupUi(this);
    10. // SEARCH TABLE UPDATE
    11. connect(ui->comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(searchTable(int)));
    12. // LOAD TABLES
    13. QTimer::singleShot(8500, this, SLOT(searchTable(50)));
    14. etc..
    15. }
    To copy to clipboard, switch view to plain text mode 

    search.cpp
    Qt Code:
    1. #include "mainwindow.h"
    2. #include "ui_MainWindow.h"
    3.  
    4. void MainWindow::searchTable(int searchID){
    5. //my code
    6. }
    To copy to clipboard, switch view to plain text mode 

    App works ok and connect() works ok. And if i call function searchTable(50); after connect() also works ok. Only when i want to use connect() and QTimer::singleShot() i get this issue in Qt Creator App Output:
    Qt Code:
    1. QObject::connect: No such slot MainWindow::searchTable(50) in ../NewApp/mainwindow.cpp:70
    2. QObject::connect: (receiver name: 'MainWindow')
    To copy to clipboard, switch view to plain text mode 
    So what am i doing wrong?

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,018
    Thanks
    280
    Thanked 816 Times in 805 Posts
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: One function in connect() and QTimer::singleShot()

    QTimer::singleShot(8500, this, SLOT(searchTable(50)));
    First thing: this is not allowed. You cannot pass an argument in a connect() statement (which is what this does, in effect - it says to connect the QTimer's timeout() signal to your searchTable() slot). However the function signatures for the signal and slot must match. QTimer::timeout() does not pass any arguments, so you can't make something up for it to pass to your slot.

    QObject::connect: No such slot MainWindow::searchTable(50) in ../NewApp/mainwindow.cpp:70
    Second, this occurs because SLOT() is a C++ macro, which converts its argument into a literal string. So your SLOT() argument is being passed as the string "searchTable(50)" and internally the connect() method is trying to match it up with a method defined in MainWindow named "searchTable(50)", which of course there isn't one. That's what the compiler error message is telling you.

    So, if what you want to do is to fire off an initial search of the table 8500 ms after your program starts (technically, 8500 ms after the MainWindow constructor exits), then you need to create a slot that takes no arguments, connect that to the timeout signal, then within that slot, call searchTable( 50 ):

    Qt Code:
    1. private slots: // in MainWindow class
    2. void doInitialSearch();
    3. void searchTable( int searchID );
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. MainWindow::MainWindow(QWidget *parent):
    2. QMainWindow(parent),
    3. ui(new Ui::MainWindow)
    4. {
    5. ui->setupUi(this);
    6.  
    7. // SEARCH TABLE UPDATE
    8. connect(ui->comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(searchTable(int)));
    9.  
    10. // LOAD TABLES
    11. QTimer::singleShot( 8500, this, SLOT( doInitialSearch() ) );
    12.  
    13. // etc..
    14. }
    15.  
    16. void MainWindow::doInitialSearch()
    17. {
    18. searchTable( 50 );
    19. }
    20.  
    21. void MainWindow::searchTable(int searchID)
    22. {
    23. //my code
    24. }
    To copy to clipboard, switch view to plain text mode 

    What are you trying to do with this 8 1/2 second delay before you do the initial search? There are probably better ways to do it than make your user sit and watch the main window for that long while nothing happens.

    If all you want is to ensure that the MainWindow is visible before doing this search, then you can implement an override of the showEvent() and make a direct call to searchTable() in that:

    Qt Code:
    1. void MainWIndow::showEvent( QShowEvent * pEvent )
    2. {
    3. QMainWindow::showEvent( pEvent ); // same as super.showEvent() in python
    4.  
    5. searchTable( 50 );
    6. }
    To copy to clipboard, switch view to plain text mode 

    or you can use a QTimer with zero timeout to accomplish the same thing. The timer signal will fire immediately after control returns to the Qt event loop (ie. after the showEvent() method exits).

    Qt Code:
    1. void MainWIndow::showEvent( QShowEvent * pEvent )
    2. {
    3. QMainWindow::showEvent( pEvent ); // same as super.showEvent() in python
    4.  
    5. QTimer::singleShot( 0, this, SLOT( doInitialSearch() ) );
    6. }
    To copy to clipboard, switch view to plain text mode 

    But I suspect there is no need for you to wait for the MainWindow to be visible before doing the initial search. Even if the window is not visible, all of the QWidgets in it are complete after the call to setupUi(), so you can fill tables, etc. and they will become visible when the MainWindow does.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  3. The following user says thank you to d_stranz for this useful post:

    ZajtiM (11th September 2021)

  4. #3
    Join Date
    Sep 2021
    Posts
    3
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: One function in connect() and QTimer::singleShot()

    Thank you for all the info.

    App will be running on fairly old PC and there is some other stuff that needs to be processed and loaded (from DB). I was forced to install x64 OS, to install QT on it and is not as fast as i would like (PC and python version App). I did search for lighter versions of Linux, because i don't need anything extra on that PC.

    Search table is not first thing user will see, when MainWindow is visible (i'm using stacked widget). This and OS/App speed was my main reason why i'm using QTimer. To let other stuff get processed and loaded before.

    QTimer with 8500 might be premature at this point, so i might change it later. I started working on C++ version 5 days ago, so i have plenty of time to change QTimer etc.

    I will be using this for now. But as i said, i might change it later.
    Qt Code:
    1. // LOAD TABLES
    2. QTimer::singleShot( 8500, this, SLOT( doInitialSearch() ) );
    3.  
    4. // etc..
    5. }
    6.  
    7. void MainWindow::doInitialSearch()
    8. {
    9. searchTable( 50 );
    10. }
    To copy to clipboard, switch view to plain text mode 

  5. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,018
    Thanks
    280
    Thanked 816 Times in 805 Posts
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: One function in connect() and QTimer::singleShot()

    This and OS/App speed was my main reason why i'm using QTimer. To let other stuff get processed and loaded before.
    Think about a design where each of the parts of "other stuff" has the ability to emit a signal when it is finished, so the next piece of "stuff" can start immediately after that. It doesn't have to be an actual Qt signal, just some flag or other indication that can be used to indicate a "finished" state. In your app, you can implement a state machine that starts the next task when each previous task says it is finished.

    For example, create an enum of status flags:

    Qt Code:
    1. enum TaskStateT
    2. {
    3. eInitialState = 0,
    4. eTask1 = 1,
    5. eTask2 = 2,
    6. // ...
    7. eTaskN = N,
    8. eFinalState = N+1
    9. } TaskState;
    10.  
    11. bool MainWindow::updateTaskState( TaskStateT state )
    12. {
    13. bool bFinished = false;
    14. TaskStateT nextState = TaskStateT( state + 1 );
    15. if ( nextState == eFinalState )
    16. bFinished = true;
    17. else
    18. doTask( nextState );
    19.  
    20. if ( bFinished )
    21. searchTable( 50 );
    22. return bFinished;
    23. }
    24.  
    25. void MainWindow::doTask( TaskStateT state )
    26. {
    27. switch( state )
    28. {
    29. case eTask1:
    30. doTask1();
    31. break;
    32.  
    33. case eTask2:
    34. doTask2();
    35. break;
    36.  
    37. // ...
    38. }
    39.  
    40. // Current task is done, update and do the next
    41. updateTaskState( state );
    42. }
    To copy to clipboard, switch view to plain text mode 

    When the MainWindow constructor is exiting, the last thing it does is call updateTaskState( eInitialState ), which kicks off the set of things that must be done. When all are finished, the initial search can start immediately. You don't need to rely on magic timing numbers which might waste the user's time or start something off too early, depending on how much time the startup stuff takes.

    If you want to keep the GUI "alive" while the initial processing is going on, you could a a call to QCoreApplication::processEvents() in the updateTaskState() method. This will run the event loop and ensure all pending events are handled. There are other ways to do it as well, such as making the state update and task execution into a signal / slot based implementation.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

Similar Threads

  1. QTimer::singleShot in while
    By Ema in forum Qt Programming
    Replies: 2
    Last Post: 28th November 2019, 20:45
  2. QTimer::singleShot stop at 12:00AM on second day
    By croliver in forum Qt Programming
    Replies: 1
    Last Post: 22nd August 2016, 17:37
  3. QTimer::singleShot(0, ... confusion
    By bjoern83 in forum Qt Programming
    Replies: 4
    Last Post: 19th April 2010, 13:45
  4. Replies: 3
    Last Post: 31st January 2010, 16:56
  5. Can we connect QTimer::SingleShot with a slot taking arguments?
    By maverick_pol in forum Qt Programming
    Replies: 4
    Last Post: 17th September 2008, 18:02

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.