在Qt的connect()中传递不同的类

Passing different classes in connect() in Qt

本文关键字:Qt connect      更新时间:2023-10-16

我正在开发一个图像编辑软件,其中包括几个类。但我需要我的代码更通用。但是当涉及到连接时,我的类有一个大问题。

QObject::connect(actionSmartContrast, SIGNAL(triggered(bool)), effectsWindow, SLOT(addSmartContrast()));
QObject::connect(actionSaturation, SIGNAL(triggered(bool)), effectsWindow, SLOT(addSaturation()));

我有一个名为"效果"的菜单,当用户点击QAction actionSmartContrast时,效果智能对比被添加到我的效果窗口。问题是,鉴于每种效果都有自己的类,我必须为每个类创建一个函数,正如您在上面的代码中看到的那样。这是非常重复的。我想通过这样做来避免这个问题:

QObject::connect(actionSmartContrast, SIGNAL(triggered(bool)), effectsWindow, SLOT(addEffect(new SmartContrast())));
QObject::connect(actionSaturation, SIGNAL(triggered(bool)), effectsWindow, SLOT(addEffect(new Saturation())));

对于函数addEffect()来说,一切都很好,因为它期望一个指向效果对象的指针,并且SmartContrast和Saturation都继承自Effect。唯一的问题是不可能像这样在connect()中传递变量。所以我想到子类化QAction并创建一个信号,每次都会返回我喜欢的类,但再次,如何告诉我的新Action类它应该返回什么类?如果我有一千个效果,我不会把QAction子类化一千次!我需要创建一个函数,例如一个指向SmartContrast对象的指针,它会猜测每次单击Action时它必须返回一个SmartContrast指针。由于继承了类Effect,所以仍然可以这样做。但我真的不知道该怎么做。任何帮助都将非常感激。提前感谢!

看起来QSignalMapper正是你要找的。

更新:

另一种方法是使用lambda(如果Qt版本和c++编译器允许):

QObject::connect(actionSmartContrast, &QAction::triggered, [effectsWindow](){ effectsWindow->addEffect(new SmartContrast()) });

有几个选项。


如果有基类指针的效果就足够了,因为你使用了虚方法,下面的解决方案应该做:

你可以创建一个中间类:

class Intermediate : public QObject 
{
    Q_OBJECT
public:
    Intermediate(QObject* parent = 0) : QObject(parent){}
signals:
    void triggerEffect(Effect*);
public slots:
    void effectTriggered()
    {
        QAction* action = qobject_cast<QAction*>(QObject::sender());
        if ( action ) {
            std::map<QAction*,Effect*>::iterator it = m_mapping.find(action);
            if ( it != m_mapping.end() )
            { emit triggerEffect( it->second ); }
        }
    }
public:
    void registerActionEffectPair(QAction* action,Effect* effect)
    { m_mapping[action]=effect; }
private:
    std::map<QAction*,Effect*> m_mapping;
};

要使用你的Effect基类作为信号和槽的类型,你必须将其注册为元类型:

qRegisterMetaType<Effect*>();

连接:

QObject::connect(intermediateInstancePtr, SIGNAL(triggerEffect(Effect*),
                 effectsWindow, SLOT(addEffect(Effect*)));

每个动作的连接看起来像:

intermediateInstancePtr->registerActionEffectPair( yourEffectAction, theEffectPtr );
QObject::connect(yourEffectAction, SIGNAL(triggered(bool)), 
                 intermediateInstancePtr, SLOT(effectTriggered()));

另一种方法是使用QObjects属性:

setProperty( "property", "value" )

为每个效果调用QAction并读取slot"addEffect"中的属性。该属性可以通过调用

来读取。
QAction* action = qobject_cast<QAction*>(QObject::sender());
if ( action ){ 
    QVariant val = action->property("property"); 
    if ( val.isValid() )
    { 
        //TODO
    }
}

since Object::sender返回负责槽调用的发送方。

之后,你可以做一个切换案例或类似的东西来区分不同的效果

我的问题终于解决了!我继承了QAction的子类,并在我的新类中添加了一个信号,它根据属性text()从我想要的类中创建一个新效果。简单的if块就足够了。谢谢大家的回答!