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

时间:2015-09-09 12:39:18

标签: c++ qt class inheritance slot

我正在开发一个包含几个类的图像编辑软件。但我需要我的代码更通用。但是当谈到连接时,我的课程遇到了很大的问题。

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(),一切都会好的,因为它需要一个指向Effect对象的指针,而SmartContrast和Saturation都从Effect继承。唯一的问题是不可能像这样传递connect()中的变量。所以我想到了继承QAction并创建一个信号,它会每次都返回我喜欢的类,但是又如何告诉我的新Action类它应该返回什么类?如果我有一千个效果,我将不会将QAction子类化为一千次!我需要创建一个函数,该函数将采用例如指向SmartContrast对象的指针,并且每次单击Action时它都会猜测它必须返回SmartContrast指针。由于类Effect的继承,这仍然是可能的。但我真的无法弄清楚如何做到这一点。任何帮助将非常感激。提前谢谢!

3 个答案:

答案 0 :(得分:1)

看起来QSignalMapper正是您正在寻找的。

更新:

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

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

答案 1 :(得分:0)

有几种选择。

如果足以拥有效果的基类指针,因为你使用例如解决方案后面的虚拟方法应该这样做:

您可以创建一个中间人类:

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调用此方法并读取插槽“addEffect”中的属性。 可以通过调用

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

因为Object :: sender返回负责插槽调用的发送方。

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

答案 2 :(得分:0)

我终于解决了我的问题!我将QAction子类化并向我的新类添加了一个信号,它根据属性text()从我想要的类创建一个新的效果。如果块足够简单。谢谢大家的答案!