Connecting to statusBar()->showMessage gives compile time error in new syntax



  • I have an old example in qt4 were a class has this connection to statusBar() of QMainWindow:

        connect(&thread, SIGNAL(transactionStarted(const QString &)),
                statusBar(), SLOT(showMessage(const QString &)));
    

    However when i change to the new compile time syntax in qt5 :

    connect(&thread, &TransactionThread::transactionStarted ,
                statusBar(), &QStatusBar::showMessage);
    

    It gives me this compile time error:

    /home/sandro/Qt/5.13.0/gcc_64/include/QtCore/qobject.h:-1:
    In instantiation of ‘static QMetaObject::Connection QObject::connect(const typename QtPrivate::FunctionPointer<Func>::Object*, Func1, const typename QtPrivate::FunctionPointer<Func2>::Object*, Func2, Qt::ConnectionType) [with Func1 = void (TransactionThread::)(const QString&); Func2 = void (QStatusBar::)(const QString&, int); typename QtPrivate::FunctionPointer<Func>::Object = TransactionThread; typename QtPrivate::FunctionPointer<Func2>::Object = QStatusBar]’:

    Is it because the slot of QStatusBar has an additional int parameter?

    [slot] void QStatusBar::showMessage(const QString &message, int timeout = 0)
    

    I thought the int gets ignored because it has a default parameter


  • Qt Champions 2018

    @sandro4912 said in Connecting to statusBar()->showMessage gives compile time error in new syntax:

    I thought the int gets ignored because it has a default parameter

    No, not in the new syntax - it's not possible there. You have to use a lambda


  • Moderators



  • i also thought about the lambda but how to pass the string send from transactionStarted to statusBar()->showMessage().

    connect(&thread, &TransactionThread::transactionStarted, [=]
        {
            statusBar()->showMessage();  // how to enter the text send with transactionStarted?
        });
    


  • @sandro4912
    I'm throwing my hat in because I'm not C++, but don't you do that by specifying the lambda as:

    connect(&thread, &TransactionThread::transactionStarted, [=](const QString &text)
        {
            statusBar()->showMessage(text);  // how to enter the text send with transactionStarted?
        });
    
    


  • @jonb

    Here is a lambda I use to create a QString for statusBar:

        connect(ui->unitVector, &QPushButton::clicked, [=](){
                                                    ui->canvas->go.setFlagAndResetAngle(4);
                                                    QString s;
                                                    s.append("Rotation about Unit Vector ");
                                                    s.append(ui->canvas->go.uv.toString());
                                                    ui->statusBar->showMessage(s, 0);});
    


  • @ofmrew
    But @sandro4912 is asking

    how to pass the string send from transactionStarted to statusBar()->showMessage()

    hence my suggestion; how is yours to do with passing a parameter on to the lambda??


  • Moderators

    @jonb said in Connecting to statusBar()->showMessage gives compile time error in new syntax:

    @sandro4912
    I'm throwing my hat in because I'm not C++, but don't you do that by specifying the lambda as:

    connect(&thread, &TransactionThread::transactionStarted, [=](const QString &text)
        {
            statusBar()->showMessage(text);  // how to enter the text send with transactionStarted?
        });
    
    

    absolutely correct!👍
    just one caveat, you can, but you shall not omit the return type

    connect(&thread, &TransactionThread::transactionStarted, [=](const QString &text)->void{});
    


  • @j-hilk
    So now C++ has found another use for ->! And I assume the [=] is an array holding this as the context or something, is that a special meaning for the =?

    I realize this isn't the place for long discussion, but ISTM with these lambdas C++ is using a lot of cryptic symbols all together!



  • @jonb said in Connecting to statusBar()->showMessage gives compile time error in new syntax:

    [=]

    [=] means that all the variables / objects are also available in the lamda body for usage. you can also specify there just a single variable from the outside.

    for more see this: https://de.cppreference.com/w/cpp/language/lambda

    the -> you can also use it for normal functions now hence its not that common.

    for example int somefunction(); becomes auto someFunction() -> int

    Anyway guys thanks for the solution


  • Moderators

    @jonb
    well, i‘m not sure what exactly the compiler does, but I assume you‘re on the right path:

    [&epsilon] capture by reference
    [&] captures all variables used in the lambda by reference
    [=] captures all variables used in the lambda by value
    [&, epsilon] captures variables like with [&], but epsilon by value
    [=, &epsilon] captures variables like with [=], but epsilon by reference

    which makes this lambda actually dangerous as the statusbar could be deleted at any time, qt offers a solution for this:

    connect(&thread, &TransactionThread::transactionStarted, statusbar, [=](const QString &text)->void{});
    

    the connect get becomes resolved, when statusbar gets deleted

    but from the naming of the variables I would say that the emitter is actually in a different thread compared to statusbar.

    I‘m not sure how Qt handles this with a Lambda, probably not good, therefore 5th connect paramater is probably a good idea

    connect(&thread, &TransactionThread::transactionStarted, statusbar, [=](const QString &text)->void{},Qt::QueuedConnection);
    


  • @j-hilk
    I knew that I had seen this before, try link text



  • i tryed to add a fifth parameter like you said:

        connect(&thread, &TransactionThread::transactionStarted, 
                [=](const QString &text)->void
        {
            statusBar()->showMessage(text);  
        }, Qt::QueuedConnection);
    

    Unfortunatey the syntax is not working with lambda.

    And yes you are right. In the MainWindow were the statusBar is there is thread launced for taskes to be computed in a second thread.



  • @sandro4912

    i tryed to add a fifth parameter like you said:

    Count your parameters, you only have 4!
    Look at @J-Hilk 's code, see what you've missed....



  • @jonb

    Note that the st in [this](const QString& st) is the name of the string that is the argument of the signal, which I use in {this->ui->statusBar->showMessage(st, 0);}



  • @ofmrew
    Try this example: ```
    void canvasResized(QString s);
    QString st = "It opened";
    emit canvasResized(st);
    connect(ui->canvas, &MyCanvas::canvasResized, [this](const QString& st){this->ui->statusBar->showMessage(st, 0);});

    I added the emit to the resizeEvent and it worked.

Log in to reply