简体   繁体   中英

C++ Qt: is it possible to create a sort of template slot?

I'm new to Qt and not a C++ expert so please bear with me with this one. I'm working on an application that has 12 different QPushButtons, but all of them perform very similar actions: they grab some value from a map and then use it to set the style for that button:

void MainWindow::on_btn01_clicked(){
    QString img=images["btn01"];
    ui->btn01->setStyleSheet("#btn01{ background-image: url(://" + img + ") }");
}

For each one of the 12 buttons I have to create a slot that only differs in the button being used. So it looks a bit weird to create 12 functions that are almost identical.

Is there a better way to do this?

Generally, there are several approaches I've seen used:

  1. The preferred method: lambda expressions.

    If you're using modern C++ (C++11 or newer), you can use a lambda function to get the exact effect you described.

    I'd expect the resulting code to look something like this:

     foreach( QPushButton * button : buttons ) { connect( button, &QPushButton::clicked, [button, &images]() { button->setStyleSheet( QString( "{ background-image: url(://%1) }" ) .arg( images[button->objectName()] ) ); }); } 

    See " Qt Slots and C++11 lambda " for more guidance on how to write lambda functions with Qt.

  2. A dirtier way: QObject::sender().

    Qt lets you use QObject::sender() within a slot to get a pointer to the object that invoked it. This has been a widely used approach for many years, but there are limitations, as described in the Qt documentation:

    Warning: As mentioned above, the return value of this function is not valid when the slot is called via a Qt::DirectConnection from a thread different from this object's thread. Do not use this function in this type of scenario.

    See " How to get sender widget with a signal/slot mechanism? " for more information.

  3. Obsolete code: QSignalMapper.

    There's a QSignalMapper class that will let you associate a signal with a bit of data, like a string, to then connect to a slot that uses this parameter. This used to exist as a convenience class in Qt but is being phased out because the lambda methodology makes it pointless.

    If you need to update code that uses QSignalMapper to remove it, this tutorial is a reasonable starting point.

You can try one more simple method, that is set the QPushButton 's object name respectively, and check the Object name in your slot and use that string. This saves you a lot of code.

Ex:
QPushButton 1 object name is set as button->setObjectName("btn01"); and respectively you can set the other names of the buttons and in your slot you could do some thing like this

void MainWindow::on_button_clicked(){
     QPushButton* btn=qobject_cast<QPushButton*>(sender()); 
     QString name=btn->objectName(); 
     QString img=images[name]; btn->setStyleSheet("#" + name + "{ background-image: url(://" + img + ");
}

and then connect all your QPushButtons to this slot

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