【问题标题】:using boost signals instead of qt使用升压信号而不是 qt
【发布时间】:2011-12-16 12:07:14
【问题描述】:

这是一个很长的尝试,但是遇到了 qt 信号形式的约束,插槽无法模板化,我只是想用 boost 信号替换它们,这是可行的选择吗?

【问题讨论】:

  • 我们怎么知道?一般来说,是的,Boost.Signals 绝对没有问题,但您可以决定 Boost 是否适合您的特定问题。

标签: c++ qt boost qt4


【解决方案1】:

您不必强制使用 qt 的信号和槽。来自Using Qt with 3rd Party Signals and Slots

可以将 Qt 与第 3 方信号/插槽机制一起使用。你 甚至可以在同一个项目中使用这两种机制。只需添加 以下行添加到您的 qmake 项目 (.pro) 文件中。

CONFIG += no_keywords

它告诉Qt不要定义moc关键字signals、slots和emit, 因为这些名称将被第 3 方库使用,例如促进。 然后继续使用带有 no_keywords 标志的 Qt 信号和槽, 只需将源代码中所有使用的 Qt moc 关键字替换为 对应的 Qt 宏 Q_SIGNALS(或 Q_SIGNAL)、Q_SLOTS(或 Q_SLOT) 和 Q_EMIT。

有一个complete explanation关于如何将boost信号连接到qt信号。


我在网上的某个地方找到了这个适配器,但不知道在哪里:

#ifndef _QT_2_FUNC_3_H_
#define _QT_2_FUNC_3_H_

#include <iostream>

#include <boost/function.hpp>
#include <boost/type_traits.hpp>

#include <QObject>

#include <libQtSignalAdapters/QtConnDefault.h>

using namespace boost;

namespace QtSignalAdapters
{

/**
* \cond
*/
template<typename SIGNATURE>
class Qt2FuncSlot3
{
public:
    typedef function<SIGNATURE> FuncType;
    typedef typename function_traits<SIGNATURE>::arg1_type ParmType1;
    typedef typename function_traits<SIGNATURE>::arg2_type ParmType2;
    typedef typename function_traits<SIGNATURE>::arg3_type ParmType3;

    Qt2FuncSlot3(const FuncType& func) :
        func_(func)
    {
    }

    void call(QObject* sender, void **arguments)
    {
        ParmType1* a1 = reinterpret_cast<ParmType1*>(arguments[1]);
        ParmType2* a2 = reinterpret_cast<ParmType2*>(arguments[2]);
        ParmType3* a3 = reinterpret_cast<ParmType3*>(arguments[3]);
        if ( func_ )
            func_(*a1,*a2, *a3);
    }

private:
    FuncType func_;
};
/**
* \endcond
*/

template<typename SIGNATURE>
class Qt2Func3 : public QObject, public QtConnDefault
{
public:
    typedef function<SIGNATURE> FuncType;
    typedef typename function_traits<SIGNATURE>::arg1_type ParmType;

    Qt2Func3(QObject* qobject, int signalIdx, const FuncType& func,
            bool initiallyConnected=true) :
        QObject(qobject),
        QtConnDefault(qobject, signalIdx),
        func_(func)
    {
        //
        // Get the next usable slot ID on this...
        //
        slotIdx_ = metaObject()->methodCount();

        //
        // Create a slot to handle invoking the boost::function object.
        //
        slot_ = new Qt2FuncSlot3<SIGNATURE>(func);

        if ( initiallyConnected )
            connect();
    }

    ~Qt2Func3()
    {
        delete slot_;
    }

    int qt_metacall(QMetaObject::Call c, int id, void **arguments)
    {
        id = QObject::qt_metacall(c, id, arguments);
        if ( id < 0 || c != QMetaObject::InvokeMetaMethod )
            return id;

        slot_->call(sender(), arguments);
        return -1;
    }

    void connect()
    {
        connect_();
    }

    void disconnect()
    {
        disconnect_();
    }

private:
    void connect_()
    {
        connected_ =
            QMetaObject::connect(qobject_, signalIdx_, this, slotIdx_);
    }

    void disconnect_()
    {
        connected_ =
            !QMetaObject::disconnect(qobject_, signalIdx_, this, slotIdx_);
    }


    FuncType func_;
    Qt2FuncSlot3<SIGNATURE>* slot_;
};

}

#endif

所以,基本上你必须重新实现qt_metacall 函数。

【讨论】:

  • Qt 5 支持将信号连接到开箱即用的任意函数 - 请参阅 qt-project.org/wiki/New_Signal_Slot_Syntax 对于 Qt 4,有一些适配器库。我在此方面的尝试以及与其他人的链接可以在 github.com/robertknight/qt-signal-tools 找到
  • @RobertKnight 应该是一个答案(如果你问我,这是一个很好的答案)。顺便说一句,他们最终对他们的信号/插槽做出了很好的决定
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-29
  • 1970-01-01
  • 1970-01-01
  • 2012-06-21
相关资源
最近更新 更多