我是靠谱客的博主 拉长康乃馨,最近开发中收集的这篇文章主要介绍qt多线程访问同一变量_Qt开发中的几点关键经验及类的元对象反射问题,值得收藏参考...,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

ba1624759d9a7f3815e017b9d6357109.png

总第41篇

本文主要总结了用Qt框架做项目开发的过程中,类的元对象MetaObject 相关的几个核心知识点,收录于此,以供大家参考,也方便于自己在工作过中可以快速温习回看。

1.元对象系统与反射

反射是指程序在运行时可以访问、检测和修改其自身状态或行为的一种能力,它和内省(type introspection)不是同的。内省机制 仅指程序在运行时对自身信息(元数据)的检测,而反射不仅包括有检测能力,还要能根据这些信息来改变程序状态或结构。

Qt的反射是基于元对象系统的, 对应的类即是QMetaObject ,所有继承自QObject的类都有元对象,都可以通过这个类的元对象metaObject()来获取属性、方法、事件等。

这里放一个类的实现例子,以便更好地理解元反射。

class TestObject : public QObject
{
    Q_OBJECT 
    Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChange) //Q_PROPERTY 注册成员变量
    Q_PROPERTY(QString text MEMBER m_text NOTIFY textChange) //AAA.注册的成员变量能够响应自定义的signals textChange
public:
    TestObject(QObject* parent);
    ~TestObject();
    void init();

    Q_INVOKABLE QString text(); //注册类的成员函数
    Q_INVOKABLE void setText(const QString& strText);
    QString m_text; //类的成员变量
signals:
    void textChange(); //自定义的signals
public slots:
    void textslot(){qDebug()<<"欢迎关注知乎:武三郎"<<endl;}  //自定义的signals响应的槽函数
};

//=========cpp文件============
TestObject::TestObject(QObject* parent) : QObject (parent)
{
    this->setObjectName("TestObject");
    connect(this, SIGNAL(textChange()),this, SLOT(textslot()));
}
TestObject::~TestObject()
{
}
void TestObject::init()
{
    qDebug()<<"init"<<endl;
}
QString TestObject::text()
{
    return m_text;
}
void TestObject::setText(const QString& strText)
{
    if (m_text == strText)
        return;
    m_text = strText;
//    emit textChange(); //有了AAA那一行,这一句不需要了
}

下面是对上面类的调用方式:

 TestObject* obj = new TestObject(this);

 qDebug()<<obj->objectName()<<endl; //输出对象的名字

 obj->setProperty("text", "hahaha");    //设置对象的属性
 qDebug()<<obj->property("text").toString()<<endl; //输出对象的属性

    //得到注册的类成员函数
 const QMetaObject* mobj = obj->metaObject();
 qDebug()<<mobj->methodCount()<<endl;
 for(int i = 0; i < mobj->methodCount(); i++)
 {
     QMetaMethod mMethod = mobj->method(i);
     QByteArray byteArray = mMethod.name();
        //输出函数类型与函数名称
     qDebug()<<mMethod.typeName()<<"->"<<QString(byteArray)<<endl; 
 }

   //调用注册的成员函数,通过Q_RETURN_ARG来获取返回值
 qDebug()<<"begin    QMetaObject::invokeMethod"<<endl;
 QString invokeString;
    //调用类的成员函数
 QMetaObject::invokeMethod(obj, "text", Qt::DirectConnection, Q_RETURN_ARG(QString, invokeString));
 qDebug()<<invokeString<<endl;

    // 再次设置text值,可以响应信号
 obj->setProperty("text", "luelueluelue");

从上面的代码中可以看出,我们可以随时获取当前类的成员变量及成员函数,这就是反射。Qt框架让C++这种静态语言有了动态的特性,这就是其强大之处。

2.元对象获取属性的方法

这里以QPushButton为例来加以说明。其示例代码如下:

QPushButton *btn = new QPushButton;
const QMetaObject *metaobject = btn->metaObject();  //获取元对象
int count = metaobject->propertyCount();  //获取属性的总数量
for (int i = 0; i < count; ++i) 
{
    QMetaProperty metaproperty = metaobject->property(i);
    const char *name = metaproperty.name();
    QVariant value = btn->property(name);
    qDebug() << name << value;
}

//其输出信息如下:
objectName QVariant(QString, "")
modal QVariant(bool, false)
windowModality QVariant(int, 0)
enabled QVariant(bool, true)
geometry QVariant(QRect, QRect(0,0 640x480))
frameGeometry QVariant(QRect, QRect(0,0 639x479))
normalGeometry QVariant(QRect, QRect(0,0 0x0))
......

从打印的信息可以看出,父类(superClass)的很多属性也获取到了,如果我们想只获取当前类的属性信息呢,如何做?这时只要将代码修改成如下形式即可:

QPushButton *btn = new QPushButton;
const QMetaObject *metaobject = btn->metaObject();
int count = metaobject->propertyCount();
int index = metaobject->propertyOffset();   //获取属性偏移
for (int i = index; i < count; ++i) 
{
    QMetaProperty metaproperty = metaobject->property(i);
    const char *name = metaproperty.name();
    QVariant value = btn->property(name);
    qDebug() << name << value;
}

其它的属性获取方式也是类似的,在QMetaObject中提供了众多的接口,可以参考接口函数进行获取。

3.项目开发中的几点经验

  • 多线程编译

若你使用Qt Creator作为IDE开发环境,那么,你可以在项目的构建套件中设置MAKEFLAGS = -j8, 从而启动多线程编译,节省程序编译时间。具体的设置方法如下图所示:

3cabb73ba1bb5a099f308d3444e93150.png
  • 可以在pro文件中标记版本号和ico图标

可以用下面的代码方式在pro文件中标记,方便简单。

VERSION            = V1.23.09.88 
Win32:RC_ICONS     = appIcon.ico
  • 移除和重置样式

移除旧的样式可用如下代码:style()->unpolish(ui->btn);

重置新的样式可用如下代码:style()->polish(ui->btn);

  • Qt提供了内置图标,封装在QStyle

QStyle::StandardPixmap 这个枚举变量中存储了70多个内置图标,可以直接在程序中调用,非常方便。

  • 根据系统位数加载程序

在程序中,可以用代码设置根据系统的位数不同来加载不同的程序,其代码示例如下:

win32 {
  if contains(DEFINES, WIN64) 
  {
      DESTDIR = $${PWD}/../../bin64
  } 
  else 
  {
      DESTDIR = $${PWD}/../../bin32
  }
}
  • findChildren查找所有子控件

可以灵活地用findChildren()函数查找该控件下的所有子控件,findChild()是查找单个控件。其示例代码如下:

//查找指定类名objectName的控件
QList<QWidget *> widgets = parentWidget.findChildren<QWidget *>("CurrentWidget");
//查找所有QLineEdit
QList<QLineEdit *> allEdits = parentWidget.findChildren<QLineEdit *>();
//只查找一级子控件,不递归
QList<QPushButton *> childButtons = parentWidget.findChildren<QPushButton *>(QString(), Qt::FindDirectChildrenOnly);
  • inherits()函数判断所属关系

在写程序的过程中,可以巧妙地使用inherits()函数来判断某个类是否属于某个类。例如:

QTimer *timer = new QTimer;         // QTimer inherits QObject
timer->inherits("QTimer");          // returns true
timer->inherits("QObject");         // returns true
timer->inherits("QAbstractButton"); // returns false 
  • 调试

当在程序调试时,若遇到很多错误,一定要从第一个错误开始,一个一个地解决,不要急着去看下面的错误,可能后面的很多错误都是由第一个错误导致的,第一个错误解决了,后面的错误也就消失了。

本文到此结束!

如果对你有帮助,请随手 点赞点喜欢

=======================================================

欢迎【关注、私信 @武三郎。我们一起交流一起进步。

最后

以上就是拉长康乃馨为你收集整理的qt多线程访问同一变量_Qt开发中的几点关键经验及类的元对象反射问题,值得收藏参考...的全部内容,希望文章能够帮你解决qt多线程访问同一变量_Qt开发中的几点关键经验及类的元对象反射问题,值得收藏参考...所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(61)

评论列表共有 0 条评论

立即
投稿
返回
顶部