zoukankan      html  css  js  c++  java
  • Qt信号之自定义数据类型

    【1】为什么需要自定义数据类型?

    内置类型毕竟很有局限性,否则为什么还需要类呢。总之,有时候,我们多么希望信号能发送自定义数据类型。

    幸哉~ Qt是支持自定义信号,且自定义信号可以发送自定义数据类型的对象。

    【2】使用方法(声明 和 注册自定义数据类型)

    1)引入头文件:#include<QMetaType>

    2)添加声明:利用宏 Q_DECLARE_METATYPE

    3)注册:利用方法 qRegisterMetaType

    【3】实例Demo

    1.文件目录(为了更好的模拟现实项目的需求,示例程序逻辑比较复杂

    2.pro文件

     1 #-------------------------------------------------
     2 #
     3 # Project created by QtCreator 2017-06-27T21:34:46
     4 #
     5 #-------------------------------------------------
     6 
     7 QT       += core gui
     8 
     9 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    10 
    11 TARGET = CustomDataType
    12 TEMPLATE = app
    13 
    14 DEFINES += QT_DEPRECATED_WARNINGS
    15 
    16 SOURCES += main.cpp
    17     MyDialog.cpp 
    18     MainWindow.cpp
    19 
    20 HEADERS  += 
    21     MyDialog.h 
    22     MainWindow.h
    23 
    24 FORMS    += 
    25     MyDialog.ui 
    26     MainWindow.ui

    3.MyDialog.h(自定义数据类型CustomDataType,使用宏Q_DECLARE_METATYPE声明数据类型

     1 #ifndef MYDIALOG_H
     2 #define MYDIALOG_H
     3 
     4 #include <QDialog>
     5 #include <QMetaType>
     6 
     7 namespace Ui
     8 {
     9     class MyDialog;
    10 }
    11 
    12 class CustomDataType
    13 {
    14 public:
    15     CustomDataType(int n = 100) : m_nValue(n) {}
    16     ~CustomDataType() {}
    17     int getValue() const { return m_nValue; }
    18     void setValue(int nValue) { m_nValue = nValue; }
    19 
    20 private:
    21     int m_nValue;
    22 };
    23 
    24 class MyDialog : public QDialog
    25 {
    26     Q_OBJECT
    27 
    28 public:
    29     explicit MyDialog(QWidget *parent = 0);
    30     ~MyDialog();
    31 
    32 public slots:
    33     void onTextChanged(const QString &str);
    34 
    35 signals:
    36     void postData(const CustomDataType &data);
    37 
    38 protected:
    39     void closeEvent(QCloseEvent *event);
    40 
    41 private:
    42     Ui::MyDialog *m_pUI;
    43     CustomDataType m_data;
    44 };
    45 
    46 Q_DECLARE_METATYPE(CustomDataType)
    47 
    48 #endif // MYDIALOG_H

    4.MyDialog.cpp(构造函数中利用qRegisterMetaType注册自定义数据类型

     1 #include "MyDialog.h"
     2 #include "ui_MyDialog.h"
     3 
     4 MyDialog::MyDialog(QWidget *parent) :
     5     QDialog(parent),
     6     m_pUI(new Ui::MyDialog)
     7 {
     8     m_pUI->setupUi(this);
     9     qRegisterMetaType<CustomDataType>("CustomDataType");
    10 
    11     connect(m_pUI->lineEdit, &QLineEdit::textChanged, this, &MyDialog::onTextChanged);
    12 }
    13 
    14 MyDialog::~MyDialog()
    15 {
    16     if (m_pUI)
    17     {
    18         delete m_pUI;
    19         m_pUI = Q_NULLPTR;
    20     }
    21 }
    22 
    23 void MyDialog::closeEvent(QCloseEvent *event)
    24 {
    25     emit postData(m_data);
    26     QDialog::closeEvent(event);
    27 }
    28 
    29 void MyDialog::onTextChanged(const QString & str)
    30 {
    31     bool bOK = false;
    32     int nNumber = str.toInt(&bOK);
    33     bOK ? m_data.setValue(nNumber) : m_data.setValue(-1);
    34 }

    5.MainWindow.h(业务类中直接定义槽函数,利用自定义数据类型作为参数类型即可

     1 #ifndef MAINWINDOW_H
     2 #define MAINWINDOW_H
     3 
     4 #include <QDebug>
     5 #include <QMainWindow>
     6 #include "MyDialog.h"
     7 
     8 namespace Ui
     9 {
    10     class MainWindow;
    11 }
    12 
    13 class MainWindow : public QMainWindow
    14 {
    15     Q_OBJECT
    16 
    17 public:
    18     explicit MainWindow(QWidget *parent = 0);
    19     ~MainWindow();
    20 
    21 public slots:
    22     void onPostData(const CustomDataType &data);
    23     void onPushButtonPress();
    24 
    25 private:
    26     MyDialog m_dialog;
    27     Ui::MainWindow *m_pUI;
    28 };
    29 
    30 #endif // MAINWINDOW_H

    6.MainWindow.cpp(connect正常连接信号与槽,并定义槽函数

     1 #include "MainWindow.h"
     2 #include "ui_mainwindow.h"
     3 
     4 MainWindow::MainWindow(QWidget *parent)
     5     : QMainWindow(parent)
     6     , m_pUI(new Ui::MainWindow)
     7 {
     8     m_pUI->setupUi(this);
     9     connect(&m_dialog, &MyDialog::postData, this, &MainWindow::onPostData);
    10     connect(m_pUI->pushButton, &QPushButton::pressed, this, &MainWindow::onPushButtonPress);
    11 }
    12 
    13 MainWindow::~MainWindow()
    14 {
    15     if (m_pUI)
    16     {
    17         delete m_pUI;
    18         m_pUI = Q_NULLPTR;
    19     }
    20 }
    21 
    22 void MainWindow::onPostData(const CustomDataType &data)
    23 {
    24     m_pUI->pushButton->setText(QString::number(data.getValue()));
    25 }
    26 
    27 void MainWindow::onPushButtonPress()
    28 {
    29     m_dialog.show();
    30 }

    7.main.cpp

     1 #include "MainWindow.h"
     2 #include <QApplication>
     3 
     4 int main(int argc, char *argv[])
     5 {
     6     QApplication a(argc, argv);
     7     MainWindow w;
     8     w.show();
     9 
    10     return a.exec();
    11 }

    8.ui文件请自理。

    【4】运行效果图

    按顺序图1->图2->图3

    图1:弹出主窗体,主窗体中央部位放置一个PushButton,点击PushButton后,弹出图2对话框。

    图2:对话框中间放置一个LineEdit,编辑数值123456,然后关闭对话框。

    图3:当图2对话框被关闭时,会发送信号,信号会附加自定义数据类型的数据对象。

    主窗体的响应槽函数从自定义数据对象中获取值,然后刷新PushButton文本为设置的数据值。

    【5】源码剖析

    1)宏 Q_DECLARE_METATYPE

    源码如下。摘自版本路径(C:QtQt5.7.15.7msvc2013includeQtCoreqmetatype.h)

     1 #define Q_DECLARE_METATYPE(TYPE) Q_DECLARE_METATYPE_IMPL(TYPE)
     2 #define Q_DECLARE_METATYPE_IMPL(TYPE)                                   
     3     QT_BEGIN_NAMESPACE                                                  
     4     template <>                                                         
     5     struct QMetaTypeId< TYPE >                                          
     6     {                                                                   
     7         enum { Defined = 1 };                                           
     8         static int qt_metatype_id()                                     
     9             {                                                           
    10                 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); 
    11                 if (const int id = metatype_id.loadAcquire())           
    12                     return id;                                          
    13                 const int newId = qRegisterMetaType< TYPE >(#TYPE,      
    14                               reinterpret_cast< TYPE *>(quintptr(-1))); 
    15                 metatype_id.storeRelease(newId);                        
    16                 return newId;                                           
    17             }                                                           
    18     };                                                                  
    19     QT_END_NAMESPACE
    20 
    21 #ifndef Q_BASIC_ATOMIC_INITIALIZER
    22 #  define Q_BASIC_ATOMIC_INITIALIZER(a) { (a) }
    23 #endif

    2) 模板函数qRegisterMetaType

    源码如下。摘自版本路径(C:QtQt5.7.15.7msvc2013includeQtCoreqmetatype.h)

     1 template <typename T>
     2 int qRegisterMetaType(const char *typeName
     3 #ifndef Q_QDOC
     4     , T * dummy = Q_NULLPTR
     5     , typename QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::DefinedType defined = 
     6         QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::Defined
     7 #endif
     8 )
     9 {
    10 #ifdef QT_NO_QOBJECT
    11     QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = typeName;
    12 #else
    13     QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
    14 #endif
    15     return qRegisterNormalizedMetaType<T>(normalizedTypeName, dummy, defined);
    16 }
    17 
    18 template<typename T, bool defined>
    19 struct MetaTypeDefinedHelper
    20 {
    21     enum DefinedType { Defined = defined };
    22 };
    23 
    24 template <typename T>
    25 int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName
    26 #ifndef Q_QDOC
    27     , T * dummy = 0
    28     , typename QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::DefinedType defined = 
    29         QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::Defined
    30 #endif
    31 )
    32 {
    33 #ifndef QT_NO_QOBJECT
    34     Q_ASSERT_X(normalizedTypeName == QMetaObject::normalizedType(normalizedTypeName.constData()), 
    35                "qRegisterNormalizedMetaType", 
    36                "qRegisterNormalizedMetaType was called with a not normalized type name, please call qRegisterMetaType instead.");
    37 #endif
    38     const int typedefOf = dummy ? -1 : QtPrivate::QMetaTypeIdHelper<T>::qt_metatype_id();
    39     if (typedefOf != -1)
    40         return QMetaType::registerNormalizedTypedef(normalizedTypeName, typedefOf);
    41 
    42     QMetaType::TypeFlags flags(QtPrivate::QMetaTypeTypeFlags<T>::Flags);
    43 
    44     if (defined)
    45         flags |= QMetaType::WasDeclaredAsMetaType;
    46 
    47     const int id = QMetaType::registerNormalizedType(normalizedTypeName,
    48                                    QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Destruct,
    49                                    QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Construct,
    50                                    int(sizeof(T)),
    51                                    flags,
    52                                    QtPrivate::MetaObjectForType<T>::value());
    53 
    54     if (id > 0) 
    55     {
    56         QtPrivate::SequentialContainerConverterHelper<T>::registerConverter(id);
    57         QtPrivate::AssociativeContainerConverterHelper<T>::registerConverter(id);
    58         QtPrivate::MetaTypePairHelper<T>::registerConverter(id);
    59         QtPrivate::MetaTypeSmartPointerHelper<T>::registerConverter(id);
    60     }
    61 
    62     return id;
    63 }

    详细内容。

    Good Good Study,Day Day Up.

    顺序 选择 循环 总结

  • 相关阅读:
    7617:输出前k大的数
    2991:2011
    7620:区间合并
    1688 求逆序对
    Magento How To Display Product Custom Option On list.phtml
    大二实习使用的技术汇总(中)
    codility上的问题 (22)
    poj 3321
    使用ViewPager实现左右“无限”滑动的万年历
    数论练习专题
  • 原文地址:https://www.cnblogs.com/Braveliu/p/7087511.html
Copyright © 2011-2022 走看看