QT系列第2节 QT中元对象系统

news2024/11/15 17:36:51

      QT是在标准C++上进行了扩展,所以就有自己的特性,其中元对象系统就是其一。元对象系统有点类似于java和go语言中的反射,让我们在编程时解决问题多了些方法和思路,关于元对象可以简单总结出以下内容项。

目录

一.元对象要点总结

二. 示例代码


一.元对象要点总结

1. QObject类是所有使用元对象系统的基类

2.在一个类private区域中声明Q_OBJECT宏,MOC(元对象编译器)为每个继承(直接或者间接)Object的类生成额外代码

3. qobject_cast:QT中的强制类型转换方法

4.属性系统 Q_PROPERTY宏定义一个返回类型为type,名称为name的属性,例如:

Q_PROPERTY(type name (...))

5.setProperty可以在运行时为对象定义一个新的属性,该属性称之为动态属性

6.Q_CLASSINFO可以增加类的附加信息,例如:Q_CLASSINFO("name", "zhangsan")

二. 示例代码

接下来用一个小demo演示一下元对象的简单应用。项目目录结构结构如下:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "qperson.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void onAdd();
    void onSub();
    void onMetaInfo();
    void onAgeChanged(unsigned age);
    void on_spinBoxFeMale_valueChanged(int arg1);

    void on_spinBoxMale_valueChanged(int arg1);

    void on_pushButtonMetaInfo_clicked();

    void on_pushButtonAdd_clicked();

    void on_pushButtonSub_clicked();

private:
    Ui::MainWindow *ui;
    QPerson* m_male;
    QPerson* m_feMale;
};
#endif // MAINWINDOW_H

qperson.h

#ifndef QPERSON_H
#define QPERSON_H

#include <QObject>

class QPerson : public QObject
{
    Q_OBJECT
Q_CLASSINFO("author", "Zhangsan")
Q_CLASSINFO("company", "ABC")
Q_CLASSINFO("version", "1.0.0.1")
    Q_PROPERTY(unsigned age READ age WRITE setAge NOTIFY ageChanged)
    Q_PROPERTY(QString name MEMBER m_name)
    Q_PROPERTY(int score MEMBER m_score)

public:
    explicit QPerson(QString name, QObject *parent = nullptr);
    unsigned age();
    void setAge(unsigned age);
    void ageAdd(unsigned age);
    void ageSub(unsigned age);
    QString getName();

private:
unsigned m_age = 18;
QString m_name = "lisi";
int m_score = 85;

signals:
    void ageChanged(unsigned age);

};

#endif // QPERSON_H

main.cpp

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QObject>
#include <QDebug>
#include <QPushButton>
#include <QLineEdit>
#include <QMetaProperty>

//元对象系统(Meta-Object System)
//QObject类是所有使用元对象系统的基类
// 在一个类private区域中声明Q_OBJECT宏
// MOC(元对象编译器)为每个继承(直接或者间接)Object的类生成额外代码

//qobject_cast:强制类型转换

//属性系统 Q_PROPERTY宏定义一个返回类型为type,名称为name的属性
//Q_PROPERTY(type name (...))

//setProperty可以在运行时为类定义一个新的属性,称之为动态属性

//类的附加信息 Q_CLASSINFO("name", "zhangsan")
//QTest* pTest = new QTest;
//qDebug << pTest->metaObject()->classInfo(0).name(); //"name"
//qDebug << pTest->metaObject()->classInfo(0).value(); //"zhangsan"


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QObject* obj = new QPushButton();
    qDebug() << obj->metaObject()->className();

    QLineEdit* edit = new QLineEdit;
    qDebug() << edit->inherits("QDebug");
    qDebug() << edit->inherits("QObject");

    m_male = new QPerson("帅男人");
    m_male->setProperty("addr", "北京");
    m_male->setProperty("income", 10000);
    m_male->setProperty("height", 180);
    connect(m_male, &QPerson::ageChanged, this, &MainWindow::onAgeChanged);

    m_feMale = new QPerson("靓女人");
    m_feMale->setProperty("addr", "上海");
    m_feMale->setProperty("income", 8000);
    m_feMale->setProperty("height", 170);
    connect(m_feMale, &QPerson::ageChanged, this, &MainWindow::onAgeChanged);

    ui->spinBoxMale->setProperty("sex", true);
    ui->spinBoxFeMale->setProperty("sex", false);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::onAgeChanged(unsigned age) {
    Q_UNUSED(age)
    QPerson *person = qobject_cast<QPerson*>(sender());
    QString name = person->getName();
    unsigned page = person->age();
    QString addr = person->property("addr").toString();
    int icnome = person->property("income").toInt();
    int height = person->property("height").toInt();
    ui->plainTextEdit->appendPlainText(name + ", " + addr +
        QString::asprintf(", 年龄:%d, 收入:%d, 身高:%d", page, icnome, height));
}

void MainWindow::onAdd()
{

}

void MainWindow::onSub()
{

}

void MainWindow::onMetaInfo()
{

}

void MainWindow::on_spinBoxFeMale_valueChanged(int arg1)
{
    Q_UNUSED(arg1)
    QSpinBox *spinBox = qobject_cast<QSpinBox*>(sender());
    if (spinBox->property("sex").toBool()) { // male
        m_male->ageAdd(spinBox->value());
    }
    else { //female
        m_feMale->ageSub(spinBox->value());
    }
}


void MainWindow::on_spinBoxMale_valueChanged(int arg1)
{
    Q_UNUSED(arg1)
    QSpinBox *spinBox = qobject_cast<QSpinBox*>(sender());
    if (spinBox->property("sex").toBool()) { // male
        m_male->ageAdd(spinBox->value());
    }
    else { //female
        m_feMale->ageSub(spinBox->value());
    }
}


void MainWindow::on_pushButtonMetaInfo_clicked()
{
    ui->plainTextEdit->clear();
    ui->plainTextEdit->appendPlainText("=====显示元对象信息=====\n");
    const QMetaObject *meta = m_feMale->metaObject();
    ui->plainTextEdit->appendPlainText(QString("类名: %1\n").arg(meta->className()));
    ui->plainTextEdit->appendPlainText("property:");
    for (int i = meta->propertyOffset(); i < meta->propertyCount(); i++) {
        //QMetaProperty prop = meta;
        QMetaProperty prop = meta->property(i);
        const char *propName = prop.name();
        QString propValue = m_male->property(propName).toString();
        ui->plainTextEdit->appendPlainText(QString("属性名:%1, 属性值:%2").arg(propName).arg(propValue));
    }
    ui->plainTextEdit->appendPlainText("");
    ui->plainTextEdit->appendPlainText("classinfo:");
    for (int i = meta->classInfoOffset(); i < meta->classInfoCount(); i++) {
        QMetaClassInfo classInfo = meta->classInfo(i);
        ui->plainTextEdit->appendPlainText(QString("name: %1, value: %2").
                                           arg(classInfo.name()).arg(classInfo.value()));
    }

}


void MainWindow::on_pushButtonAdd_clicked()
{
     m_male->ageAdd(1);
}


void MainWindow::on_pushButtonSub_clicked()
{
     m_feMale->ageSub(1);
}

qperson.cpp

#include "qperson.h"

QPerson::QPerson(QString name, QObject *parent)
    : QObject{parent}
{
    m_name = name;
}

unsigned QPerson::age()
{
    return m_age;
}

void QPerson::setAge(unsigned age) {
    emit ageChanged(age);
    m_age = age;
}

void QPerson::ageAdd(unsigned age) {
    m_age += age;
    emit ageChanged(m_age);
}

void QPerson::ageSub(unsigned age) {
    m_age -= age;
    emit ageChanged(m_age);
}

QString QPerson::getName() {
    return m_name;
}

 mainwindow.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>507</width>
    <height>357</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QHBoxLayout" name="horizontalLayout">
    <item>
     <widget class="QPlainTextEdit" name="plainTextEdit"/>
    </item>
    <item>
     <layout class="QVBoxLayout" name="verticalLayout">
      <item>
       <layout class="QGridLayout" name="gridLayout">
        <item row="0" column="0">
         <widget class="QLabel" name="label">
          <property name="text">
           <string>男人:</string>
          </property>
         </widget>
        </item>
        <item row="0" column="1">
         <widget class="QSpinBox" name="spinBoxMale">
          <property name="value">
           <number>20</number>
          </property>
         </widget>
        </item>
        <item row="0" column="2">
         <widget class="QPushButton" name="pushButtonAdd">
          <property name="text">
           <string>增大</string>
          </property>
         </widget>
        </item>
        <item row="1" column="0">
         <widget class="QLabel" name="label_2">
          <property name="text">
           <string>女人:</string>
          </property>
         </widget>
        </item>
        <item row="1" column="1">
         <widget class="QSpinBox" name="spinBoxFeMale">
          <property name="value">
           <number>18</number>
          </property>
         </widget>
        </item>
        <item row="1" column="2">
         <widget class="QPushButton" name="pushButtonSub">
          <property name="text">
           <string>减小</string>
          </property>
         </widget>
        </item>
       </layout>
      </item>
      <item>
       <widget class="QPushButton" name="pushButtonMetaInfo">
        <property name="text">
         <string>元对象信息</string>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QPushButton" name="pushButtonClear">
        <property name="text">
         <string>清空</string>
        </property>
       </widget>
      </item>
      <item>
       <spacer name="verticalSpacer">
        <property name="orientation">
         <enum>Qt::Vertical</enum>
        </property>
        <property name="sizeHint" stdset="0">
         <size>
          <width>20</width>
          <height>68</height>
         </size>
        </property>
       </spacer>
      </item>
     </layout>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>507</width>
     <height>22</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections>
  <connection>
   <sender>pushButtonClear</sender>
   <signal>clicked()</signal>
   <receiver>plainTextEdit</receiver>
   <slot>clear()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>438</x>
     <y>73</y>
    </hint>
    <hint type="destinationlabel">
     <x>253</x>
     <y>210</y>
    </hint>
   </hints>
  </connection>
 </connections>
</ui>

运行效果如下:

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/83512.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux转发性能评估与优化之——转发瓶颈分析与解决方案

线速问题 很多人对这个线速概念存在误解。认为所谓线速能力就是路由器/交换机就像一根网线一样。而这&#xff0c;是不可能的。应该考虑到的一个概念就是延迟。数据包进入路由器或者交换机&#xff0c;存在一个核心延迟操作&#xff0c;这就是选路&#xff0c;对于路由器而言&…

软件工程复习简略

软件工程复习简略1.什么是软件生存周期&#xff1f;通常可划分为哪些阶段&#xff1f;2.简述需求分析要经过哪些步骤&#xff0c;每个步骤的作用。3.详细设计有哪些常用工具&#xff1f;&#xff08;注意Pad图的画法&#xff09;4.软件测试的目的和原则是什么&#xff1f;5.测试…

pythonselenium自动化测试实战项目(完整、全面)

前言 之前的文章说过&#xff0c; 要写一篇自动化实战的文章&#xff0c; 这段时间比较忙再加回家过11一直没有更新博客&#xff0c;今天整理一下实战项目的代码共大家学习。&#xff08;注:项目是针对我们公司内部系统的测试&#xff0c;只能内部网络访问&#xff0c;外部网络…

【SpringCloud负载均衡】【源码+图解】【三】LoadBalancer的工作原理

【SpringCloud负载均衡】【源码图解】【二】LoadBalancer配置 目录3. LoadBalancer的工作原理3.1 创建LoadBalancerRequest3.2 创建上下文3.2.1 properties3.2.2 configurations3.2.3 contexts3.3 获取ReactiveLoadBalancer3.4 获取ServiceInstance3.5 向serviceInstance请求结…

Java要学到什么程度才可以找工作?

Java为不同的集合提供了一个集合框架。集合基于数据结构&#xff0c;比如常见的&#xff1a;列表、数组、集合、哈希图等等。因此&#xff0c;在研究集合时&#xff0c;最好了解一点数据结构的相关知识。 主要副题&#xff1a; List Set Map ArrayList LinkedList Queue…

web3:智能合约-虚拟机(EVM、HVM、WASM、MOVE)

在区块链上&#xff0c;用户通过运行部署在区块链上的合约&#xff0c;完成需要共识的操作。而为智能合约提供运行环境的便是对应的虚拟机。 目录EVM基础概念技术细节EVM的存储模型交易在EVM的执行普通转账交易智能合约的创建或者调用EVM机器语言与现有的虚拟机科技作比较EVM的…

Java中类的复用

类的复用&#xff08;组合与继承&#xff09; 第一种方法&#xff1a;只需在新类中产生现有类的对象&#xff0c;新类由现有类组成&#xff0c;也称为组合&#xff0c;该方法只是复用了现有程序代码的功能&#xff1b; 第二种方法&#xff1a;按现有类来创建新类&#xff0c;…

m基于LPF-VMD和KELM的鸟群优化算法的风速预测算法matlab仿真

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 1).使用 LPF-VMD 对风速时间序列进行分解&#xff0c; 得到一个低频的趋势分量以及 n 个由 VMD 分解得 到的 BIMF。 2).对 LPF-VMD 分解得到的各分量分别建立 KELM 预测模型&#xff0c;采用 B…

【进阶】C语言第二课:升级你的指针(1)

目录 &#x1f929;前言&#x1f929;&#xff1a; 一、字符指针&#x1f92f;&#xff1a; 1.字符指针的使用&#x1f99d;&#xff1a; 2.常量字符串&#x1f98a;&#xff1a; 3.相关面试题分析&#x1f423;&#xff1a; 二、指针数组&#x1f9d0;&#xff1a; 三、数…

vue+nodejs公益图书借阅捐赠管理系统

公益图书捐赠管理系统 用户信息&#xff1a;id、用户名、密码、捐书数量&#xff08;管理员端可以点击跳转查看详情&#xff09;、上传电子书数量&#xff08;管理员端可以点击跳转查看详情&#xff09;、借阅图书数量&#xff08;管理员端可以点击跳转查看详情&#xff09;&am…

利用全长转录组多重阵列测序检测同源异构体

哈佛大学和麻省理工学院近期发表了“High-throughput RNA isoform sequencing using programmable cDNA concatenation.”研究论文中&#xff0c;将 cDNA 串联成可用于长读长测序最佳的单分子的技术应用于肿瘤浸润 T 细胞的单细胞 RNA 测序,提高了寻找可变剪接基因的准确度&…

秒懂:JCTool 的 Mpsc 高性能无锁队列 (史上最全+10W字长文)

文章很长&#xff0c;而且持续更新&#xff0c;建议收藏起来&#xff0c;慢慢读&#xff01;疯狂创客圈总目录 博客园版 为您奉上珍贵的学习资源 &#xff1a; 免费赠送 :《尼恩Java面试宝典》 持续更新 史上最全 面试必备 2000页 面试必备 大厂必备 涨薪必备 免费赠送 经典…

C# 修饰符

一 访问控制符 二 static 1 static 的字段、方法、属性是属于整个类的 ① static方法中&#xff0c;不能访问实例变量&#xff1b; ② 调用static方法时&#xff0c;直接用类名访问 Console.Write();Math.Sqrt(); Convert.ToDateTime();DateTime.Parse String.Copy(a);Strin…

【JavaSE】javaSE练习项目——>《简易图书管理系统》

目录 前言&#xff1a; 1、项目实现要求 2、设计思路流程 设计思路&#xff1a; 登录后菜单的实现效果&#xff1a; 3、代码实现&#xff08;大体框架&#xff09; Main类 book包 Book类 BookList类 user包 User类 AdminUser(管理员)类 NormalUser&#xff08;普通…

Hibernate Validator 使用详解

目录 Hibernate Validator的依赖 Hibernate Validator 支持注解 空与非空检查 Boolean值检查 日期检查 数值检查 其他 Hibernate-validator扩展约束 Hibernate Validator 校验 简单对象校验 嵌套对象校验 Hibernate Validator 分组校验 静态分组 动态分组 动态分…

【软件测试】刚入职后,快速适应新的工作需要做啥?

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 入职一家新公司后&a…

基于AD8226的环境光传感器电路

人们越来越多地认为环境光是一种能源,可用于驱动心率监控器、浴室灯具、远程天气传感器和其他低功耗器件。对于能量采集系统,最关键的是精确测量环境光的能力。本设计思路将描述一种简单的低成本电路,可以根据环境光的强度按一定比例提供电压。 所用传感器是一款光敏电阻(L…

spring framework 容器

org.springframework.beans 和 org.springframework.context 包是 Spring Framework 的 IoC 容器的基础。 这里需掌握两个体系结构&#xff0c;BeanFactory 和 ApplicationContext。 BeanFactory 主要接口&#xff0c;可分为三级&#xff1a; BeanFactory 是顶层容器&#xf…

Nacos 配置中心之主动拉取

客户端 客户端的配置有两种方式来维持,一是客户端主动拉取,而是客户端长轮询更新 配置文件的种类 1、本地配置文件: 本地就已经存在的配置文件 2、 本地缓存文件: 从服务端获取的保存在了本地 (本地生成了文件) 3、 cacheData 缓存数据: 内存中缓存的配置文件数据 客户端主动获…

【分享】学浪PC端登录分析及实现

本文所有教程及源码、软件仅为技术研究。不涉及计算机信息系统功能的删除、修改、增加、干扰,更不会影响计算机信息系统的正常运行。不得将代码用于非法用途,如侵立删!学浪PC端登录分析及实现 环境 win10Fiddlerchrome学浪PC端登录:aHR0cHM6Ly9zdHVkZW50LWFwaS5peWluY2Fpc2…