Results 1 to 17 of 17

Thread: Passing message to MainWindow status bar - using connect

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Aug 2020
    Posts
    18
    Qt products
    Qt5

    Default Passing message to MainWindow status bar - using connect

    I like to keep track of application progress - using MainWindow "status bar." .
    No problem within MainWindow form , however,
    in actual case

    how do I use signal emitted by my "tab" widget class to activate slot / status bar in MainWindow.

    I am currently processing the signals using "connect" but
    it is limited to interact with "parent" class only.

    I need to "cross-connect " "signal/slot" between the tab class and MainWindow class
    I am lost using the real code - here is my pseudo code

    connect ( tab class , SIGNAL tab class signal "finshed", MainWindow class , SLOT set "statusBar (message )

    Help will be appreciated

  2. #2
    Join Date
    Aug 2020
    Posts
    18
    Qt products
    Qt5

    Default Re: Passing message to MainWindow status bar - using connect

    I like to add another example of croos-conncetion.
    In MainWindow I have a simple button (scan) "click" which starts a bluez function "inquiry" and gets disabled / greyed out as part of interactive response.

    ui->scan->setEnabled(false);

    After the "inquiry" is done detecting near-by devices ( few seconds) I want to re-enable the button.

    Now I am re-enabling this button in blues signal processing function and my enabling code does not work.

    ( At this point I am not sure where / which "scan" button is being processed by "ui" )

    ui->scan->setEnabled(true);


    I need to pass the enabling code BACK to MainWindow - using signal / slot.

  3. #3
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    4,719
    Thanks
    259
    Thanked 760 Times in 750 Posts
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: Passing message to MainWindow status bar - using connect

    connect ( tab class , SIGNAL tab class signal "finshed", MainWindow class , SLOT set "statusBar (message )
    Again, you need to read the Qt documentation on signals and slots so you can understand how they work. Look at the Qt examples to see how they are used in real code.

    The C++ function signature for a slot must match the function signature for the signal. In other words, your slot can't be defined with an argument that does not exist in the signal (like your 'message' argument). If a class emits a signal with no arguments, the signal / slot mechanism can't just make something up to put in the argument defined for the slot it is connected to.

    So if you want a widget in one of your tabs to send a string (message) back to your main window so the main window can display it in the status bar, then you need do do several things:

    1 - define a signal in your widget with a suitable name (sendStatus maybe) and a QString argument: void sendStatus( const QString & message )
    2 - define a slot in your MainWindow class with the same signature (void displayStatusMessage( const QString & message ))
    3 - implement code in this slot to display the string argument (message) in the status bar
    4 - when you create the widget for the tab, connect the widget's signal to the main window's slot.
    5 - when your widget wants to display a status message, call "emit sendStatus( "Here is a message" );" Since that signal is now connected to the main window's slot, the slot will take care of displaying it

    The main window's slot should look something like this:

    Qt Code:
    1. // MainWindow.h
    2.  
    3. class MainWindow : public QMainWindow
    4. {
    5. Q_OBJECT
    6.  
    7. // ...
    8.  
    9. protected slots:
    10. void displayStatusMessage( const QString & message );
    11.  
    12. // ...
    13. };
    14.  
    15. // MainWindow.cpp
    16.  
    17. // MainWindow constructor:
    18. {
    19. //...
    20.  
    21. MyWidget * pWidget = new MyWidget();
    22. myTabWidget->addTab( myWidget, "My Widget" );
    23.  
    24. connect( pWidget, SIGNAL( sendStatus( const QString & ) ), this, SLOT( displayStatusMessage( const QString & ) ) );
    25.  
    26. // ...
    27. }
    28.  
    29. void MainWindow::displayStatusMessage( const QString & message )
    30. {
    31. QStatusBar * pStatusBar = statusBar();
    32. pStatusBar->showMessage( message, 5000 ); // A 5 second timeout
    33. }
    To copy to clipboard, switch view to plain text mode 

    Alternatively, since QStatusBar::showMessage() is a slot itself, you could connect this slot directly to your widget's signal, which will cause it to display with a zero timeout. In this case, the message will be displayed until it is cleared or replaced by some other new message, either from your code or frfom a tooltip (which also uses the status bar):

    Qt Code:
    1. // MainWindow constructor
    2.  
    3. MyWidget * pWidget = new MyWidget();
    4. myTabWidget->addTab( myWidget, "My Widget" );
    5.  
    6. QStatusBar * pStatusBar = statusBar();
    7. connect( pWidget, SIGNAL( sendStatus( const QString & ) ), pStatusBar, SLOT( showMessage( const QString & ) ) );
    To copy to clipboard, switch view to plain text mode 

    This works even though the slot has an extra argument which defaults to zero.

    Remember, code for signals is automatically created by the MOC compiler. All you have to do is declare the signal in your widget class and that's it:

    Qt Code:
    1. // MyWidget.h
    2.  
    3. class MyWidget : public QWidget
    4. {
    5. Q_OBJECT
    6.  
    7. // ...
    8. signals:
    9. void sendStatus( const QString & status );
    10.  
    11. //...
    12. };
    13.  
    14. // NOTHING goes in MyWidget.cpp to implement this signal.
    To copy to clipboard, switch view to plain text mode 

    Any place in MyWidget where you want to update the status, you simply do this:

    Qt Code:
    1. void MyWidget::SomeMethod()
    2. {
    3. emit sendStatus( "Status from SomeMethod" );
    4. }
    To copy to clipboard, switch view to plain text mode 

    Also remember that signals and slots both have void return values. You cannot return anything from a slot unless you pass an argument that is either a pointer or a reference that the slot can modify:

    Qt Code:
    1. signals:
    2. void someSignal( int & returnValue );
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. public slots:
    2. void someSlot( int & returnValue )
    3. {
    4. returnValue = 42;
    5. }
    To copy to clipboard, switch view to plain text mode 

    Just remember that if the same signal is connected to more than one slot, the -last- slot to handle the signal will wipe out any value set by previous slots.
    <=== 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.

  4. #4
    Join Date
    Aug 2020
    Posts
    18
    Qt products
    Qt5

    Default Re: Passing message to MainWindow status bar - using connect

    OK, I did implemented your suggestion, however, it compiles , no errors , but no "final" message in MainWindow status bar.

    My implementation is different since I already have the (tab) widget constructed.
    I am still struggling with keeping code and forms "in line" with each other, so I am not sure if my conncet code implementation is "legal".

    I am enclosing (part of) my "work in progress " code to show I did try both message outputs - via function and "direct" to status bar.

    What would be a logical way to find out progress of the signal emit via connect all the way to status bar message display ? ?

    I am currently using "cout" and I did verify I do "emit", but not sure how to trace if to the "slot / statusBar " in MainWindow.


    Qt Code:
    1. BT_FormDeviceInquiry *deviceIquiry = new BT_FormDeviceInquiry();
    2.  
    3. /* allready in form
    4.   MyWidget * pWidget = new MyWidget();
    5.   myTabWidget->addTab( myWidget, "My Widget" );
    6. */
    7.  
    8. // connect( pWidget, SIGNAL( sendStatus( const QString & ) ), this, SLOT( displayStatusMessage( const QString & ) ) );
    9. // MESSAGE VIA FUNCTION
    10. connect( deviceIquiry, SIGNAL( sendStatus( const QString & ) ), this, SLOT( displayStatusMessage( const QString & ) ) );
    11.  
    12. // TODO post message directly to status bar
    13. QStatusBar * pStatusBar = statusBar();
    14. // connect(deviceIquiry, SIGNAL( sendStatus( const QString & ) ), pStatusBar, SLOT( showMessage( const QString & ) ) );
    15. connect(deviceIquiry, SIGNAL( sendStatus( const QString & ) ),
    16. this, SLOT( ui->statusbar->showMessage(const QString & ) ) );
    To copy to clipboard, switch view to plain text mode 

  5. #5
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    4,719
    Thanks
    259
    Thanked 760 Times in 750 Posts
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: Passing message to MainWindow status bar - using connect

    connect(deviceIquiry, SIGNAL( sendStatus( const QString & ) ),
    this, SLOT( ui->statusbar->showMessage(const QString & ) ) );
    No, you didn't implement my suggestion.

    Qt Code:
    1. ui->statusbar->showMessage(const QString & )
    To copy to clipboard, switch view to plain text mode 

    This is some sort of hybrid of a function declaration and a function call. It will compile because of the way the SLOT() macro is implemented, but at runtime it won't do anything because the syntax is wrong.

    The SLOT() macro takes as its argument the function signature of the slot you want to be called, not the call to the function itself. The connect() argument that preceeds the SLOT() macro (called "receiver" in the QObject::connect() documentation) is the specific QObject instance which contains the function to be called. The particular form of the connect() statement you are using takes the arguments to the SIGNAL() and SLOT() macros and turns them into quoted strings. At runtime, the boilerplate code generated by the MOC compiler tries to match these strings up with actual signals and slots defined for the two objects that you are trying to connect. If it finds a match, it makes the actual connection between object instances and function pointers.

    The string "ui->statusbar->showMessage( const QString & )" doesn't translate to anything the MOC compiler has generated, so the connect() fails at runtime (and you should see a message in your debugger output that says exactly that).

    Go back and read my previous post again and implement what I wrote. I gave you two options: 1) implement a slot in your MainWindow class to receive the signal from your widget class and post it to the status bar with a timeout, or 2) connect directly to the status bar's showMessage() slot with no timeout.
    <=== 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.

  6. #6
    Join Date
    Aug 2020
    Posts
    18
    Qt products
    Qt5

    Default Re: Passing message to MainWindow status bar - using connect

    Ok, thanks for explaining why code working as stand alone code will not work in "connect".

    ui->statusbar->showMessage(const QString & )

    Now help me to understand why the first connect code , result of intelisense assistance does not produce the statusBar message

    Qt Code:
    1. connect(deviceIquiry,SIGNAL(sendStatus(QString)),this,SLOT(displayStatusMessage(QString)));
    To copy to clipboard, switch view to plain text mode 

    How can I trace the "connect" process to find what I did wrong / missed?

    I did check and my "emit" code executes.
    I get no compile errors nor run time errors.

    And I really appreciate your help.

  7. #7
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    4,719
    Thanks
    259
    Thanked 760 Times in 750 Posts
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: Passing message to MainWindow status bar - using connect

    Post the code for this:

    1 - Your declaration of the signal in whatever class it is that "deviceIquiry" is an instance of.
    2 - Your declaration of the slot in MainWindow.h
    3 - Your implementation of the slot in MainWindow.cpp
    4 - The code in your MainWindow constructor where you create the "deviceIquiry" instance and connect it to the slot
    5 - Your code from one of the places where you emit the signal.

    I did check and my "emit" code executes.
    How did you check?
    <=== 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.

  8. #8
    Join Date
    Aug 2020
    Posts
    18
    Qt products
    Qt5

    Default Re: Passing message to MainWindow status bar - using connect

    Qt Code:
    1. MainWindow::MainWindow(QWidget *parent) :
    2. QMainWindow(parent),
    3. ui(new Ui::MainWindow)
    4. {
    5. ui->setupUi(this);
    6. #ifdef TRACE
    7. std::cout <<"TRACE START MainWindow Constructor File "<< __FILE__ << " Function " <<__FUNCTION__<<" @line "<< __LINE__<< std::endl;
    8. #endif
    9. BT_FormDeviceInquiry *deviceIquiry = new BT_FormDeviceInquiry();
    10. if(connect(deviceIquiry,SIGNAL(sendStatus(QString)),this,SLOT(displayStatusMessage(QString))))
    11. std::cout <<"SUCCESS SIGNALS / SLOTS CONNECTED "<< std::endl;
    12. else
    13. {
    14. std::cout <<"******************************************************FAILED CONNECTION " <<std::endl;
    15. exit(-1);
    16. }
    17. #ifdef TRACE
    18. std::cout <<"TRACE END MainWindow Constructor File "<< __FILE__ << " Function " <<__FUNCTION__<<" @line "<< __LINE__<< std::endl;
    19. #endif
    20. }
    To copy to clipboard, switch view to plain text mode 



    Does not get called
    Qt Code:
    1. void MainWindow::displayStatusMessage( const QString & message )
    2. {
    3. #ifdef TRACE
    4. std::cout <<"TRACE \nFile "<< __FILE__ << "\nFunction " <<__FUNCTION__<<" \n@line "<< __LINE__<< std::endl;
    5. #endif
    6. /*
    7.   QStatusBar * pStatusBar = statusBar();
    8.   pStatusBar->showMessage( message, 5000 ); // A 5 second timeout
    9.   */
    10.  
    11. ui->statusbar->showMessage(message,5000);
    12. }
    To copy to clipboard, switch view to plain text mode 

    slot declaration in MainWIndow
    Qt Code:
    1. int WriteStatus(const QString *message);
    2. // int WriteStatus(char *message);
    3.  
    4. public slots:
    5. void displayStatusMessage( const QString & message );
    To copy to clipboard, switch view to plain text mode 




    emit signal - using TRACE to verify execution
    Qt Code:
    1. void BT_FormDeviceInquiry::scanFinished()
    2. {
    3. #ifdef TRACE
    4. std::cout <<"TRACE \nFunction "<< __FUNCTION__ << "\nFile " << __FILE__<< "\n@Line # "<< __LINE__<< std::endl;
    5. #endif
    6.  
    7. #ifdef BYPASS
    8. CurrentTime();
    9. QString text = "STATE start scan for near-by BT devices finished ";
    10. StatusBar(&text);
    11. #endif
    12.  
    13. ui->scan->setEnabled(true); // TODO does not re_enable button
    14.  
    15. // test signal
    16. #ifdef TRACE
    17. std::cout <<"TRACE START emit sendStatus \nFunction "<< __FUNCTION__ << "\nFile " << __FILE__<< "\n@Line # "<< __LINE__<< std::endl;
    18. #endif
    19.  
    20. emit sendStatus( "Status from SomeMethod" );
    21.  
    22. #ifdef TRACE
    23. std::cout <<"TRACE END emit sendStatus \nFunction "<< __FUNCTION__ << "\nFile " << __FILE__<< "\n@Line # "<< __LINE__<< std::endl;
    24. #endif
    25.  
    26. }
    To copy to clipboard, switch view to plain text mode 

    declaration of signal
    Qt Code:
    1. public:
    2. // 82920202
    3. int TestFunction();
    4. // declare signal
    5. signals:
    6. void sendStatus( const QString & status );
    7.  
    8. // CCC chnaged to publick private:
    9. public:
    10. QBluetoothDeviceDiscoveryAgent *discoveryAgent;
    11. QBluetoothLocalDevice *localDevice;
    12. Ui_DeviceDiscovery *ui;
    To copy to clipboard, switch view to plain text mode 

  9. #9
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    4,719
    Thanks
    259
    Thanked 760 Times in 750 Posts
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: Passing message to MainWindow status bar - using connect

    if(connect(deviceIquiry,SIGNAL(sendStatus(QString) ),this,SLOT(displayStatusMessage(QString))))
    std::cout <<"SUCCESS SIGNALS / SLOTS CONNECTED "<< std::endl;
    Do you see this message? Note that connect() does not return a bool, it returns an object of type QMetaObject::Connection. However, this class does have a bool() cast operator, which does return true if the connection was made. So you lucked out with this.

    #ifdef TRACE
    std::cout <<"TRACE START emit sendStatus \nFunction "<< __FUNCTION__ << "\nFile " << __FILE__<< "\n@Line # "<< __LINE__<< std::endl;
    #endif

    emit sendStatus( "Status from SomeMethod" );

    #ifdef TRACE
    std::cout <<"TRACE END emit sendStatus \nFunction "<< __FUNCTION__ << "\nFile " << __FILE__<< "\n@Line # "<< __LINE__<< std::endl;
    #endif
    This isn't really testing for anything. The "emit" will happen even if there are no slots connected to the signal. If no slots are connected, there is no error, Qt just eats the signal and does nothing.

    Change your connect() statement to this and see if that helps:

    Qt Code:
    1. connect( deviceIquiry, SIGNAL( sendStatus( const QString & ) ), this, SLOT( displayStatusMessage(const QString & ) ) )
    To copy to clipboard, switch view to plain text mode 

    Your original code does not really match the function signatures for either the signal or the slot.

    Qt Code:
    1. /*
    2.   QStatusBar * pStatusBar = statusBar();
    3.   pStatusBar->showMessage( message, 5000 ); // A 5 second timeout
    4.   */
    5.  
    6. ui->statusbar->showMessage(message,5000);
    To copy to clipboard, switch view to plain text mode 

    And have you verified that the pointer returned by QMainWindow::statusBar() is the same as your ui->statusbar? If not, maybe you should consider implementing that part of the slot in the same way as I did in my example.
    <=== 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.

  10. #10
    Join Date
    Aug 2020
    Posts
    18
    Qt products
    Qt5

    Default Re: Passing message to MainWindow status bar - using connect

    Allow me to take this one step ant at time.

    Do you see this message? Note that connect() does not return a bool, it returns an object of type QMetaObject::Connection. However, this class does have a bool() cast operator, which does return true if the connection was made. So you lucked out with this.

    Yes I see the message.

    "if" construct been checking for VALIDITY of content of parenthesis NOT for bool which is NOT basic C construct since conception.
    ( All these "false " "bool" etc. are crutches to make think complicated , not helpful...)
    The "connect" returns "handle" (YUCK ) and Qt implementation of language is doing exactly what it suppose to do - checks for VALIDITY of "handle".


    Changing the connect to EXACTLY match the SIGNAL / SLOT "signature" did not change the results - no message.
    Adding some more scaffolding I actually get helpful errors

    Qt Code:
    1. if(
    2. (bool)
    3. connect(
    4. deviceIquiry,SIGNAL(sendStatus(const QString &)),
    5. this,SLOT(displayStatusMessage(QString &))
    6. )
    7. )
    8. std::cout <<"SUCCESS SIGNALS / SLOTS CONNECTED "<< std::endl;
    9. else
    10. {
    11. std::cout <<"FAILED CONNECTION " <<std::endl;
    12. exit(-1);
    13. }
    To copy to clipboard, switch view to plain text mode 


    function BT_FormDeviceInquiry
    file ../CAT_BT/bt_formdeviceinquiry.cpp
    line # 143
    SUCCESS SIGNALS / SLOTS CONNECTED
    FAILED CONNECTION
    BT_FormDeviceInquiry *deviceIquiry : No such device or address
    BT_FormDeviceInquiry *deviceIquiry : Resource temporarily unavailable
    TEST: Resource temporarily unavailable
    QObject::connect: No such slot MainWindow::displayStatusMessage(QString &) in ../CAT_BT/mainwindow.cpp:62
    QObject::connect: (sender name: 'DeviceDiscovery')
    QObject::connect: (receiver name: 'MainWindow')
    /media/z/DEV_COPY_LABEL/Qt/QT/qtconnectivity/examples/bluetooth/build-CAT_BT-Desktop-Debug/btscanner exited with code 255

    I'll check the other stuff soon.
    Again, appreciate your support.

  11. #11
    Join Date
    Aug 2020
    Posts
    18
    Qt products
    Qt5

    Default Re: Passing message to MainWindow status bar - using connect

    Checking pointer ??

    When I add

    ui->statusbar->showMessage(message,5000);

    as part of plain "push button" function - it outputs message to status bar.

    Is that a good enough "pointer" test ?


    My "connect" never gets to execute displayStatusMessage function.


    Qt Code:
    1. void MainWindow::displayStatusMessage( const QString & message )
    2. {
    3. #ifdef TRACE
    4. std::cout <<"TRACE \nFile "<< __FILE__ << "\nFunction " <<__FUNCTION__<<" \n@line "<< __LINE__<< std::endl;
    5. #endif
    6. /*
    7.   QStatusBar * pStatusBar = statusBar();
    8.   pStatusBar->showMessage( message, 5000 ); // A 5 second timeout
    9.   */
    10. ui->statusbar->showMessage(message,5000);
    11. }
    To copy to clipboard, switch view to plain text mode 

  12. #12
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    4,719
    Thanks
    259
    Thanked 760 Times in 750 Posts
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: Passing message to MainWindow status bar - using connect

    "if" construct been checking for VALIDITY of content of parenthesis NOT for bool which is NOT basic C construct since conception.
    No, an "if" clause evaluates the expression inside it and attempts to convert it to something that can be interpreted as "true" or "false". It doesn't check "validity", whatever you think that is. To keep old code from breaking, if the expression can be converted to an integer zero (false) or non-zero (true), this will compile - so that includes numeric expressions, pointers (0 / nullptr vs. non-null), and other such things. It does not include instances of classes. As I previously said, QObject::connect() returns an instance of the class QMetaObject::Connection. It does not return a "handle" in the Windows "HANDLE" sense, it returns a class instance. A Windows HANDLE -can- be treated as a numeric value, so it can be evaluated in an if() clause. QMetaObject::Connection is not a "HANDLE", it is a C++ class. If QMetaObject::Connection did not have a QMetaObject::Connection::operator bool() cast operator, your statement would not compile, even if you try to cast it to (bool). You would get an "incompatible types" or "type conversion" error, whatever error message your compiler puts out in those cases.

    SUCCESS SIGNALS / SLOTS CONNECTED
    FAILED CONNECTION
    If your source code really is what you posted above, this combination is impossible. Either control goes through the TRUE branch or it goes through the FALSE branch, not both. The rest of the diagnostic messages you quoted doesn't make any sense either unless your real code is different from what you posted.

    Do you have two variables named "deviceIquiry"? Maybe one of them is a member variable of MainWindow, and that one is being "shadowed" by the local variable with the same name that is defined in the MainWindow constructor?

    Again, appreciate your support.
    You know, I am trying to help you out here, but you seem to be intent on just going your own way and not listening to what I and others are telling you. Making a custom signal-slot pair and connection is not hard, especially when all you want to do is to pass a string from instances of one class to another.
    <=== 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. Passing data between MainWindow and my class
    By r2com in forum Qt Programming
    Replies: 10
    Last Post: 27th July 2016, 17:04
  2. Showing long message in status bar
    By riarioriu3 in forum Qt Programming
    Replies: 1
    Last Post: 11th July 2012, 12:26
  3. Replies: 6
    Last Post: 10th February 2011, 12:10
  4. Status bar message tend to disappear
    By maverick_pol in forum Qt Programming
    Replies: 4
    Last Post: 16th July 2010, 01:15
  5. Passing Pixmaps between MainWindow and Dialog
    By ramstormrage in forum Qt Programming
    Replies: 28
    Last Post: 20th April 2008, 14:32

Tags for this Thread

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.