简体   繁体   English

C ++ Qt:是否可以创建一种模板插槽?

[英]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. 我是Qt的新手而不是C ++专家所以请耐心等待。 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: 我正在开发一个具有12种不同QPushButtons的应用程序,但它们都执行非常类似的操作:它们从地图中获取一些值,然后使用它来设置该按钮的样式:

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. 对于12个按钮中的每一个,我必须创建一个仅在使用的按钮上有所不同的插槽。 So it looks a bit weird to create 12 functions that are almost identical. 因此,创建几乎完全相同的12个函数看起来有点奇怪。

Is there a better way to do this? 有一个更好的方法吗?

Generally, there are several approaches I've seen used: 一般来说,我见过几种方法:

  1. The preferred method: lambda expressions. 首选方法:lambda表达式。

    If you're using modern C++ (C++11 or newer), you can use a lambda function to get the exact effect you described. 如果您使用的是现代C ++(C ++ 11或更高版本),则可以使用lambda函数来获得所描述的精确效果。

    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. 有关如何使用Qt编写lambda函数的更多指导,请参阅“ Qt Slots和C ++ 11 lambda ”。

  2. A dirtier way: QObject::sender(). 更脏的方式:QObject :: sender()。

    Qt lets you use QObject::sender() within a slot to get a pointer to the object that invoked it. Qt允许您在插槽中使用QObject :: sender()来获取指向调用它的对象的指针。 This has been a widely used approach for many years, but there are limitations, as described in the Qt documentation: 这已经是一种广泛使用的方法多年,但有一些限制,如Qt文档中所述:

    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. 警告:如上所述,当通过Qt :: DirectConnection从与该对象的线程不同的线程调用插槽时,此函数的返回值无效。 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. 过时的代码: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. 有一个QSignalMapper类,它允许您将信号与一些数据(如字符串)相关联,然后连接到使用此参数的插槽。 This used to exist as a convenience class in Qt but is being phased out because the lambda methodology makes it pointless. 这曾经作为Qt中的一个便利类存在,但正逐步淘汰,因为lambda方法使它毫无意义。

    If you need to update code that uses QSignalMapper to remove it, this tutorial is a reasonable starting point. 如果您需要更新使用QSignalMapper删除它的代码, 本教程是一个合理的起点。

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. 您可以尝试一种更简单的方法,即分别设置QPushButton的对象名称,并检查插槽中的对象名称并使用该字符串。 This saves you a lot of code. 这为您节省了大量代码。

Ex: 例如:
QPushButton 1 object name is set as button->setObjectName("btn01"); QPushButton 1对象名设置为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 然后将所有QPushButtons连接到此插槽

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM