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

2023-11-11

      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>

运行效果如下:

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QT系列第2节 QT中元对象系统 的相关文章

  • Qt/c++ 随机字符串生成[重复]

    这个问题在这里已经有答案了 我正在创建一个应用程序 需要生成多个随机字符串 几乎就像一个由一定长度的 ASCII 字符组成的唯一 ID 这些字符混合有大写 小写 数字字符 有没有 Qt 库可以实现这一点 如果没有 在纯 C 中生成多个随机字
  • QSpinBox 输入 NaN 作为有效值

    我正在尝试扩展 QSpinBox 以能够输入 NaN 或 nan 作为有效值 根据文档 我应该使用 textFromValue valueFromText 和 validate 函数来完成此操作 但我无法让它工作 因为它仍然不允许我输入除数
  • 如何在 C++ 运行时更改 QML 对象的属性?

    我想在运行时更改 QML 对象的文本 我尝试如下 但文本仍然为空 这是后端类 class BackEnd public QObject Q OBJECT Q PROPERTY QString userFieldText READ userF
  • 有没有办法在没有 QApplication::exec() 的情况下使用 Qt?

    有没有一种安全的方法可以在不调用 QApplication exec 的情况下使用 Qt 我有许多不同的对象正在对多个资源执行长期进程 至少其中一个正在与 Web 应用程序服务器进行通信 我正在制作一个 GUI 应用程序 提示用户在正确的时
  • Qt中如何获取鼠标在屏幕上的位置?

    我想获取屏幕上的鼠标坐标 我怎样才能在 Qt 中做到这一点 在 Windows 上 使用 C 我正在做类似答案中建议的事情对于这个问题 https stackoverflow com q 11737665 1420197 正如文档所述 QC
  • GoQt 致命错误:QAbstractAnimation:没有这样的文件或目录

    我尝试编译 Qt 来开发桌面应用程序 我按照 Qt 网站上的官方 wiki 指南的说明进行操作 当我尝试go run示例文件夹中的示例 我收到错误 去运行 home pinkya rabbit workspace go1programs s
  • Qt - 如何粘合两个窗口并将它们移动在一起?

    就像qmmp Qt 音乐播放器ui设计一样 这两个或三个窗口实际上在同一个窗口中 因为只有一个dock图标 并且这些窗口可以一起移动并相互附着 我看了源码 好像有用QDockWidget 但我真的不知道如何获得它的细节 当您手动移动辅助窗口
  • 禁用 QML Slider 的鼠标滚轮

    我希望能够滚动Flickable使用鼠标滚轮 或触摸板上的两根手指 不改变Sliders它可能包含 示例代码及结果应用 import QtQuick 2 7 import QtQuick Window 2 2 import QtQuick
  • 如何使用 Qtimer 添加 1 秒延迟

    我目前有一个方法如下 void SomeMethod int a Delay for one sec timer gt start 1000 After one sec SomeOtherFunction a 这个方法实际上是一个附加到信号
  • 使用 Visual Studio 2013 构建 Qt 5.2.1 的静态版本

    几天来我一直在尝试使用 Visual Studio 2013 构建 Qt 的静态版本 我就是不明白我做错了什么 System Windows 7 64 位 Visual Studio 2013 仍安装 Visual Studio 2012
  • 更改 Qt OpenGL 窗口示例以使用 OpenGL 3.3

    我正在尝试更改 Qt OpenGL 示例以使用更现代的 opengl 版本 330 似乎合适 所以我做了 在 main cpp 上设置版本和配置文件 设置着色器版本 更改着色器以使用统一 它现在构建没有任何错误 但我只看到一个空白窗口 我错
  • 如何使QTableView类的restoreState()和saveState()正常工作?

    首先 我想说 我的问题已经在这里讨论过 并且这里是 https stackoverflow com questions 1163030 qt qtableview and horizontalheader restorestate 但答案并
  • Qt 插槽是否与其他代码并行运行?

    在此函数示例中 void MyClass myFunction emit MySignal1 emit MySignal2 如果我有slot1倾听MySignal1 and slot2倾听MySignal2 1 Is slot1总是会在之前
  • 如何检测QTableView中的双击

    我正在使用 PyQt 创建 GUI 应用程序 在继承自 QTableView 的视图中 需要检测用户双击行时选择的行 该表可以排序 但不能编辑 我该怎么做 注意 尝试了 doubleClicked int 信号 它是由鼠标按钮发出的 而不是
  • 同时从多个流中捕获、最佳方法以及如何减少 CPU 使用率

    我目前正在编写一个应用程序 该应用程序将捕获大量 RTSP 流 在我的例子中为 12 个 并将其显示在 QT 小部件上 当我超过大约 6 7 个流时 问题就会出现 CPU 使用率激增并且出现明显的卡顿 我认为它不是 QT 绘制函数的原因是因
  • Qt表格小部件,删除行的按钮

    我有一个 QTableWidget 对于所有行 我将一列的 setCellWidget 设置为按钮 我想将此按钮连接到删除该行的函数 我尝试了这段代码 它不起作用 因为如果我只是单击按钮 我不会将当前行设置为按钮的行 ui gt table
  • Qt - 获取互联网上托管的网页的源代码(HTML 代码)

    我想获取网页的源代码 HTML 例如StackOverflow的主页 这是我到目前为止编写的代码 QNetworkAccessManager manager QNetworkReply response manager get QNetwo
  • Qt 安装程序框架 - 如何在卸载时仅删除某些文件和文件夹

    我使用 Qt 安装程序框架 如何确保在卸载时仅删除某些文件或文件夹 而不是像当前那样删除安装文件夹中的所有文件 先感谢您 您可以覆盖默认行为component createOperations对于卸载程序 然后使用手动指定每个卸载路径com
  • 如何访问Loader的sourceComponent中的QML对象?

    我可能需要读取或写入的一些属性Loader s sourceComponent来自一些外部函数 访问该房产的方式是什么x里面的对象的Loader s sourceComponent import QtQuick 2 0 Item width
  • 来自另一个类的 Qt C++ GUI 调用

    我通过 gui 拖放创建了一个按钮和一个文本浏览器 UI 以及单击按钮功能是在 mainwindow cpp 中创建的 有一个 main cpp 但这是无关紧要的 因为在单击开始按钮之前程序不会启动 include mainwindow h

随机推荐

  • 第一章 红绿灯数据采集

    第一章 红绿灯数据采集 华为hilens主控 AI实现自主导航和红绿灯控制 总章目录 第一章 Hilens红绿灯数据采集 第二章 ModelArts数据处理 第三章 ModelArts模型训练 第四章 ModelArts模型转换 第五章 H
  • 国内各大互联网公司技术团队站点

    利用闲暇时间整理了一份国内各大互联网公司的相关技术站点 希望能够对大家有所帮助 也欢迎各位帮忙补充 1 腾讯系列 名称 地址 财付通设计中心TID 地址 fitdesign tencent com QQ邮箱博客 地址 blog mail q
  • 使用linux服务器相关命令

    最近需要在云GPU服务器上跑模型 初次接触这样的形式 因此记录一下比较常用的命令 一 ssh登陆指令 1 常见登陆方式 ssh 用户名 服务器ip 2 有端口号和用户名的登陆方式 ssh l 用户名 服务器ip p 端口号 二 scp指令
  • git push遇到503错误的解决方案:The requested URL returned error: 503

    git remote set url origin https your user name github com your user name your project name git 参考了这个blog https www shuiz
  • 球谐函数在环境光照中的使用原理

    在三维空间中如何对场景光照进行球谐函数展开 图形学论文解析与复现 Spherical Harmonic Lighting The Gritty Details 首先 对场景中某像素点的漫反射光照进行计算 L p w
  • 机房 机柜的保养 和清理

    https www linuxprobe com clear idc html
  • 取消Allegro的PCB文件在Drill Legend后产生的过孔标注的方法

    在cadence的PCB编辑完成后 Drill Legend生产钻孔说明表 程序会自动加上钻孔的标注 如图 给后续的再次编辑带来困扰 关闭方法 关闭图层Manufacturing gt Ncdrill Figure即可关闭钻孔标注
  • float取小数点后几位_float类型的存储方式

    在c语言中float函数是单精度的 它在内存中以二进制的形式存储 分为符号位 阶码与尾数三部分 符号位最为简单 如果你存储的是正数那么符号数就是0 如果是负数 则为1 下面 我以13 625为例说明阶码与尾数的表示方法 首先 我们取出13
  • 深入理解程序设计使用linux汇编语言(一)

    在编译运行第四章power函数遇到报错 报错信息Invalid SP address 0xffffdf2c 通过gdb定位到程序 gt 0x40007e
  • mysql数据库,oracle数据库中对字段的拼接方法

    mysql数据库 oracle数据库中对字段的拼接方法 1 简介 在日常开发中 常常有将多个字段拼接进行sql操作的场景 比如做模糊查询 我这里分两种环境阐述 1 在数据库中的写法 2 在mybatis或mybatisplus中的写法 2
  • Matlab绘图-详细全面(图)

    Matlab绘图 强大的绘图功能是Matlab的特点之一 Matlab提供了一系列的绘图函数 用户不需要过多的考虑绘图的细节 只需要给出一些基本参数就能得到所需图形 这类函数称为高层绘图函数 此外 Matlab还提供了直接对图形句柄进行操作
  • 自动驾驶(五十三)---------浅析深度学习与自动驾驶

    之前有分析过深度学习和自动驾驶的关系 但是主要是在视觉的基础上来分析的 连接 这里想从各个角度来分析深度学习在自动驾驶中的应用 如果你正好有这方面的需要 不妨选择一个着力点 笔者从事自动驾驶3年来 也处于瓶颈期 需要在一个特定的领域深挖 这
  • 华为OD机试真题-最大花费金额-2023年OD统一考试(B卷)

    题目描述 双十一众多商品进行打折销售 小明想购买自己心仪的一些物品 但由于受购买资金限制 所以他决定从众多心仪商品中购买三件 而且想尽可能的花完资金 现在请你设计一个程序帮助小明计算尽可能花费的最大资金数额 输入描述 输入第一行为一维整型数
  • 区块链技术生态的设计

    区块链技术生态的设计 详见 区块链技术生态
  • String-字符串替换

    例子 原始字符串 String demo aback 文章目录 一 replace 字符或者字符串替换 1 使用方法 2 源码 二 replaceAll 多个正则替换 1 使用方法 2 源码 三 replaceFirst 首次出现替换 1
  • 移动端兼容宝典大全,专治各种不适

    古人学问遗无力 少壮功夫老始成 移动端兼容宝典大全 专治各种不适 你是否也曾为浏览器各种的不兼容而苦恼 尤其是IE这个牛皮癣 这篇文章可能会给你帮助哦 常码字不易 出精品更难 没有特别幸运 那么请先特别努力 别因为懒惰而失败 还矫情地将原因
  • 小程序调整文章正文样式:

    1 官网地址 npm install github markdown css 2 案例 右键 gt 另存为 gt 导入 使用css文件 引入的css已markdown body的class名开头 适配时禁止github markdown转换
  • Openlayers API-Select点击要素图层

    Select是交互事件中的一种 用于选择矢量图层上的几何图形 添加选择交互事件后 点击地图上的几何图形或者将鼠标移动到几何图形上时 将获取到几何图形的相关信息 我们可以将选择的几何图形进行高亮显示 使用起来很简单 首先创建一个Select对
  • Xcode MacOS与clang c++版本关系

    关于clang https en wikipedia org wiki Clang 7 September 2017 Clang 5 0 0 released 19 January 2018 Clang becomes default co
  • QT系列第2节 QT中元对象系统

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