实验目的
创建TPerson类,年龄增加事件发射信号
创建Dailog窗体,将TPerson类发射来的信号,绑定到窗体槽函数
使用QMetaObject显示类元数据 ,显示类名称,遍历类属性Property名称及属性值,
遍历打印类元数据的 classInfo信息
TPerson类
tperson.h
声明ageChanged信号
#ifndef TPERSON_H
#define TPERSON_H
#include <QObject>
class TPerson : public QObject
{
Q_OBJECT
Q_CLASSINFO("author","cc")
Q_CLASSINFO("company","companyC")
Q_CLASSINFO("version","1.0.0")
//定义age属性
Q_PROPERTY(int age READ age WRITE setAge NOTIFY ageChanged FINAL)
Q_PROPERTY(int score MEMBER m_score)
Q_PROPERTY(QString name MEMBER m_Name)
private:
int m_age=10;
int m_score=79;
QString m_Name;
public:
explicit TPerson(QString aName, QObject *parent = nullptr);
~TPerson();
int age();
int setAge(int value);
void incAge();
signals:
void ageChanged(int value);
};
#endif // TPERSON_H
tperson.cpp
在incAge方法中emit发射信号
#include "tperson.h"
TPerson::TPerson(QString aName,QObject *parent):QObject(parent)
{
this->m_Name = aName;
}
TPerson::~TPerson()
{
//析构函数
}
int TPerson::age()
{
return this->m_age;
}
int TPerson::setAge(int value){
this->m_age = value;
emit ageChanged(this->m_age); //发射信号 用于后面绑定界面变化的槽来执行
}
void TPerson::incAge()
{
this->m_age++;
emit ageChanged(this->m_age);
}
Dialog
dialog.h
声明do_ageChanged执行方法
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include "tperson.h"
QT_BEGIN_NAMESPACE
namespace Ui {
class Dialog;
}
QT_END_NAMESPACE
class Dialog: public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = nullptr);
~Dialog();
private slots:
void do_ageChanged(int value);
void do_spinChanged(int value);
void on_btnClassInfo_clicked();
void on_btnClear_clicked();
void on_btnGirlInc_clicked();
void on_btnBoyInc_clicked();
private:
TPerson *boy;
TPerson *girl;
Ui::Dialog *ui;
};
#endif // DIALOG_H
dialog.cpp
通过connect 将&TPerson::ageChanged方法 ,将信号连接到槽执行方法:本类中&Dialog::do_agedChanged
#include "dialog.h"
#include "ui_dialog.h"
#include "tperson.h"
#include "QMetaProperty"
Dialog::Dialog(QWidget *parent):
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
//初始化数据
boy = new TPerson("张铁蛋",this);
boy->setProperty("score",94);
boy->setProperty("age",11);
boy->setProperty("gender","Boy");
connect(boy,&TPerson::ageChanged,this,&Dialog::do_ageChanged); //将类发送过来的信号,传递到窗体类中槽执行函数
girl = new TPerson("李丽",this);
girl->setProperty("score",98);
girl->setProperty("age",12);
girl->setProperty("gender","Girl"); // 添加一个动态属性 gender
connect(girl,&TPerson::ageChanged,this,&Dialog::do_ageChanged);
ui->spinBoy->setProperty("isBoy",true);//在spinBox中添加一个动态属性isBoy
ui->spinGirl->setProperty("isBoy",false);
//将spinBoy、SpinGirl的valueChanged事件 绑定到 本类中的槽执行函数
connect(ui->spinBoy,&QSpinBox::valueChanged,this,&Dialog::do_spinChanged);
connect(ui->spinGirl,&QSpinBox::valueChanged,this,&Dialog::do_spinChanged);
}
Dialog::~Dialog()
{
delete ui;
}
//girl长大一岁
void Dialog::on_btnGirlInc_clicked()
{
girl->incAge();// TPerson→incAge →emit ageChanged→connet this do_ageChanged
}
//Boy长大一岁
void Dialog::on_btnBoyInc_clicked()
{
boy->incAge();
}
void Dialog::do_ageChanged(int value)
{
//Q_UNUSED()函数在程序中的作用,就如它所代表的英文一样,unused,即无用的意思。即Q_UNUSED()函数在程序中没有实质性的作用,用来避免编译器警告。
Q_UNUSED(value);
TPerson *person = qobject_cast<TPerson *>(sender());
QString hisName= person->property("name").toString();
QString hisGender = person->property("gender").toString();
int hisAge = person->property("age").toInt();
QString str = QString("%1,%2,年龄=%3").arg(hisName).arg(hisGender).arg(hisAge);
ui->textBox->appendPlainText(str);
}
void Dialog::do_spinChanged(int value)
{
QSpinBox *spin = qobject_cast<QSpinBox *>(sender());//获取信号发射者
if(spin->property("isBoy").toBool()){//根据发送过来自定义动态属性 判断 是哪个组件
boy->setAge(value);
}
else {
girl->setAge(value);
}
}
void Dialog::on_btnClear_clicked()
{
ui->textBox->clear();
}
void Dialog::on_btnClassInfo_clicked()
{
QObject *obj =boy;
const QMetaObject *meta = obj->metaObject();
ui->textBox->clear();
ui->textBox->appendPlainText(QString("类名称:%1").arg(meta->className()));
ui->textBox->appendPlainText("property");
//获取类属性及属性值
for(int i=meta->propertyOffset();i<meta->propertyCount();i++)
{
const char* propName=meta->property(i).name();
QString propValue= obj->property(propName).toString();
QString str=QString("属性名称%1,属性值%2").arg(propName).arg(propValue);
ui->textBox->appendPlainText(str);
}
//获取类信息
ui->textBox->appendPlainText("");
ui->textBox->appendPlainText("classInfo");
for(int i=meta->classInfoOffset();i<meta->classInfoCount();i++)
{
QMetaClassInfo classInfo =meta->classInfo(i);
QString str= QString("ClassInfo Name=%1, Value=%2").arg(classInfo.name()).arg(classInfo.value());
ui->textBox->appendPlainText(str);
}
}
类的元信息
通过QMetaObject 来遍历Property属性,打印属性名称,属性值,需要引用QMetaProperty
#include "QMetaProperty"
通过 QMetaClassInfo获取meta的CalssInfo
void Dialog::on_btnClassInfo_clicked()
{
QObject *obj =boy;
const QMetaObject *meta = obj->metaObject();
ui->textBox->clear();
ui->textBox->appendPlainText(QString("类名称:%1").arg(meta->className()));
ui->textBox->appendPlainText("property");
//获取类属性及属性值
for(int i=meta->propertyOffset();i<meta->propertyCount();i++)
{
const char* propName=meta->property(i).name();
QString propValue= obj->property(propName).toString();
QString str=QString("属性名称%1,属性值%2").arg(propName).arg(propValue);
ui->textBox->appendPlainText(str);
}
//获取类信息
ui->textBox->appendPlainText("");
ui->textBox->appendPlainText("classInfo");
for(int i=meta->classInfoOffset();i<meta->classInfoCount();i++)
{
QMetaClassInfo classInfo =meta->classInfo(i);
QString str= QString("ClassInfo Name=%1, Value=%2").arg(classInfo.name()).arg(classInfo.value());
ui->textBox->appendPlainText(str);
}
}
效果