QtのQFlags及び関連マクロ学習のまとめ

11744 ワード

http://blog.csdn.net/dbzhang800/article/details/6734273
起源
私達の5軸テーブルのために制御インターフェースを定義します.
  • は、まず、エンムタイプを定義する.5つのエニュメレーション値は、それぞれの軸
  • を表す.
    enum AxisId {
        Axis_X,
        Axis_Y,
        Axis_Z,
        Axis_R,
        Axis_T
    };
  • インターフェースクラスを定義する
  • 、ある絶対位置moveA
  • に移動します.
  • は相対量moveR
  • を移動する.
  • ゼロ操作doHome
  • class StageControl:public QObject
    {
        Q_OBJECT
    public:
        StageControl();
    public slots:
        void moveA(const QMap<AxisId, double> &);
        void moveR(const QMap<AxisId, double> &);
        void doHome(const QList<AxisId>&);
    ...
    二つの移動操作は何も言うことはないはずです.命令はいつも含まれています.どの軸がどこに移動しますか?
    doHomeに対しては、どの軸の動きをコントロールする必要がありますか?一つのQListで十分ですが、なんだかよくないです.となりました
    enum AxisId{
        Axis_X = 0x01,
        Axis_Y = 0x02,
        Axis_Z = 0x04,
        Axis_R = 0x08,
        Axis_T = 0x10
    };
    class StageControl:public QObject
    {
    ...
        void doHome(int axes);
    これでいいです. doHome(Axis| Axis Y) しかし、パラメータはintです.どうやって安全ではないですか?もし適当に整数を伝えたらどうすればいいですか?
    QFlags
    一度しか見たことがないですが、ずっと見たことがありません.
    今になって、Manualをひっくり返して、ソースコードをねらってみました.えっと、もともとQFlagsはこんなに簡単なものです.
    簡単に次のコードを書きます.
    typedef QFlags<AxisId> AxisIds;
    
    StageControl:public QObject
    {
    ...
    void doHome(AxisIds axes);
    しかし、これは仕事ができません.doHomeは最適なマッチング関数を見つけられません.全体を定義する必要があります.
    AxisIds operator|(AxisId, AxisId);
    関数
    タイプ定義(typedef)とオペレータのリロードは、マクロQudeCLAREuFLAGSである.
    Q_DECLARE_FLAGS(AxisIds, AxisId)
    和宏QuDECLAREUOPAERATORS
    Q_DECLARE_OPERATORS_FOR_FLAGS(AxisIds)
    やったこと
    注:この二つのマクロはQtのメタオブジェクトシステムとは関係がありません.
    QuFLAGSとQuENUMS
    前の2つのマクロと違って、この2つはmocによって処理されるマクロです.C++プリプロセッサにとっては、ただのスペースです.
    元の対象の情報と関係がある以上、先にQMetaObjectのManualをねらうつもりです.意外にも!QFlagsの影がなくて、ただ
  • QMetaEnum QMetaObject:enumerator(int index)const
  • int QMetaObject:enumeratoCount()const
  • int QMetaObject:enumerator Offset()const
  • int QMetaObject:indexOfEnumerator(const char*name)const
  • これらのもの
    QuFLAGSのマンツールを詳しく見ています.
    Note:This macro Taes care of register ing individual flags values with the meta-object system,so it is unnecessary to use QuENUMS()in addition to this macro.何を言いましたか?QuFLAGSを使ったと教えてくれます.QuENUMSを使う必要がありません.
    どういうことですか
    例を書いてテストしてみます.
  • は、QuFLAGS(QuENUMSを用いず)のみを使用して、メタオブジェクト情報を登録する
  • .
  • は次に、メタオブジェクト内の列挙量情報
  • を出力する.
    class StageControl:public QObject
    {
        Q_OBJECT
    
    public:
        enum AxisId{
            Axis_X = 0x01,
            Axis_Y = 0x02,
            Axis_Z = 0x04,
            Axis_R = 0x08,
            Axis_T = 0x10
        };
        //Q_ENUMS(AxisId)
        Q_DECLARE_FLAGS(AxisIds, AxisId)
        Q_FLAGS(AxisIds)
    
        StageControl()
        {
            const QMetaObject * mobj = metaObject();
            for (int i=mobj->enumeratorOffset(); i<mobj->enumeratorCount(); ++i) {
                QMetaEnum menum = mobj->enumerator(i);
                qDebug()<<"name: "<<menum.name();
                for (int ii=0; ii<menum.keyCount(); ++ii) {
                    qDebug()<<menum.key(ii);
                }
            }
        }
    };
    結果は以下の通りです
    name:  AxisIds 
    Axis_X 
    Axis_Y 
    Axis_Z 
    Axis_R 
    Axis_T 
    ちょっと面白いです.QuENUMSだけを使った時の結果を比較してみます.
    name:  AxisId 
    Axis_X 
    Axis_Y 
    Axis_Z 
    Axis_R 
    Axis_T 
    ふふ、二つは全部使いますか?
    name:  AxisId 
    Axis_X 
    Axis_Y 
    Axis_Z 
    Axis_R 
    Axis_T 
    name:  AxisIds 
    Axis_X 
    Axis_Y 
    Axis_Z 
    Axis_R 
    Axis_T
    元対象システムに相当する二つのQMetaEnumオブジェクトがあります.
    また何を見ますか?
    mocで生成されたファイルを参照してください.
    QuENUMSとQuFLAGSが同時に使用されると、確かに二つのQMetaEnumオブジェクトが生成される.
    static const uint qt_meta_data_StageControl[] = {
    
     // content:
           6,       // revision
           0,       // classname
           0,    0, // classinfo
           0,    0, // methods
           0,    0, // properties
           2,   14, // enums/sets
           0,    0, // constructors
           0,       // flags
           0,       // signalCount
    
     // enums: name, flags, count, data
          13, 0x0,    5,   22,
          20, 0x1,    5,   32,
    
     // enum data: key, value
          28, uint(StageControl::Axis_X),
          35, uint(StageControl::Axis_Y),
          42, uint(StageControl::Axis_Z),
          49, uint(StageControl::Axis_R),
          56, uint(StageControl::Axis_T),
          28, uint(StageControl::Axis_X),
          35, uint(StageControl::Axis_Y),
          42, uint(StageControl::Axis_Z),
          49, uint(StageControl::Axis_R),
          56, uint(StageControl::Axis_T),
    
           0        // eod
    };
    
    static const char qt_meta_stringdata_StageControl[] = {
        "StageControl\0AxisId\0AxisIds\0Axis_X\0"
        "Axis_Y\0Axis_Z\0Axis_R\0Axis_T\0"
    };
    その他
    急に分かりました.なぜマンツールの中にいますか?
    enum Qt::WindowType
    flags Qt::WindowFlags
    または
    enum Qt::WindowState
    flags Qt::WindowStates
    いつもペアで紹介します!
    もともと、無意識のうちに、WindowTypeのエニュメレーション値はWidget/Windowのようなシングル値であり、DialogはWindowFlagsに属しています.
        enum WindowType {
            Widget = 0x00000000,
            Window = 0x00000001,
            Dialog = 0x00000002 | Window,
            Sheet = 0x00000004 | Window,
            Drawer = 0x00000006 | Window,
            Popup = 0x00000008 | Window,
            Tool = 0x0000000a | Window,
            ...
        }
        Q_DECLARE_FLAGS(WindowFlags, WindowType)
    もともとこのような違いはありませんでした.
    最初の例に戻ると、私が一番よく使うのはX、Y、Rの三つの軸です.そこで、エンムをこう定義します.
    enum AxisId{
        Axis_X = 0x01,
        Axis_Y = 0x02,
        Axis_Z = 0x04,
        Axis_R = 0x08,
        Axis_T = 0x10,
        Axis_2D = Axis_X|Axis_Y|Axis_R
    };
    後記
    めちゃくちゃです.ここにメモしておきます.