目录
1.概述
2.元对象系统
3.属性系统
(1)属性定义
(2)属性的使用
(3)动态属性
(4)类的附加信息
4.信号与槽
5.元对象特性实例
QObject *obj = new QPushButton;obj->metaObject()->className();//返回类的名称字符串,这里返回“QPushButton”
QTimer *timer = new QTimer;//QTimer是QObject的子类timer->inherits("QTimer");//返回truetimer->inherits("QObject");//返回truetimer->inherits("QAbstractButton");//返回false,QTimer不是QAbstractButton的子类
QObject *obj = new QMyWidget;//变量obj定义为QObject指针,但它实际指向QMyWidget类QWidget *widget = qobiect_cast(obj);//obj实际是QMyWidget类,是QWidget的子类,动态投射成功 //qobiect_cast()并不区分Qt内建的类型和用户自定义的类型QMyWidget *myWidget = qobiect_cast(obj);//obj实际是QMyWidget类,故投射其自身,也可以动态投射成功 QLabel *label = qobiect_cast(obj);//返回label为NILL,因为QMyWidget不是QLabel的子类。
Q_PROPERTY(type name(READ getFunction [WRITE setFunction] |MEMBER memberName [(READ getFunction | WRITE setFunction)])[RESET resetFunction][NOTIFY notifySignal][REVISION int][DESIGNABLE bool][SCRIPTABLE bool][STOREO bool][USER bool][CONSTANT][FINAL])
Q_PROPERTY(bool focus READ hasFocus)Q_PROPERTY(bool enabled READ isEnabIed WRITE setEnab1ed)Q_PROPERTY(QCursor cursor READ cursor WRITE setCursor RESET unsetCursor)
QPushButton*button = new QPushButton;QOject*object = button;object->setProperty("flat",true);bool isFlat=object->property("flat");
editName->setProperty("required',"true");comboSex->setProperty("required',''true");checkAgree->set?roperty("required","true");
class QMyClass:public QObject{Q_OBJECTQ_CLASSINFO("author","Wang"Q_CLASSINFO("company“,"UPC")Q_CLASSINFO("version","3.0.1")public:...};
(1)connect()函数的不同参数形式
connect(sender,SIGNAL(signal()),receiver, SLOT(slot()));
connect(spinNum,SIGNAL(valueChanged(int)),this,SLOT(updateStatus(int));
connect(lineEdit,&QLineEdit::textChanged, this, &widget::on_textChanged);
void QSpinBox::valueChanged(inti)void QSpinBox::valueChanged(const QString &text)
void onVaIueChanged(int i);
connect(spinNum,&QSpinBox::valueChanged,this,&widget::onValueChanged);
Qt::AutoConnection(缺省值):如果信号的接收者与发射者在同一个线程,就使用Qt::Direct Connection方式:否则使用Qt::QueuedConnection方式,在信号发射时自动确定关联方式。 Qt::DirectConnection:信号被发射时槽函数立即执行,槽函数与信号在同一个线程。 Qt::QueuedConnection:在事件循环回到接收者线程后执行槽函数,槽函数与信号在不同的线程。
Qt::BlockingQueuedConnection:与Qt::QueuedConnection相似,只是信号线程会阻塞直到槽
(2)使用sender()获得信号发射者
QSpinBox *spinBox = qobject_cast( sender() );
(3) 自定义信号及其使用
Class QPerson : public QObject{Q_OBJECTprivate:int m_age = 10;public:void incAge();signals:void ageChanged(int value);};
void QPerson::incAge(){m_age++;emit ageChanged(m_age);//发射信号}
//qperson.h文件
#ifndef QPERSON_H
#define QPERSON_H
#include
class QPerson : public QObject
{
Q_OBJECT
Q_CLASSINFO("author","Wang")
Q_CLASSINFO("company","UPC")
Q_CLASSINFO("version","1.0.0")
Q_PROPERTY(int age READ age WRITE setAge NOTIFY ageChanged)
Q_PROPERTY(QString name MEMBER m_name)
Q_PROPERTY(int score MEMBER m_score)
private:
int m_age=10;
QString m_name;
int m_score=79;
public:
explicit QPerson(QString fName, QObject *parent = nullptr);
int age();
void setAge(int value);
void incAge();
signals:
void ageChanged( int value);
public slots:
};
#endif // QPERSON_H
//qperson.cpp文件
#include "qperson.h"
QPerson::QPerson(QString fName,QObject *parent) : QObject(parent)
{ //构造函数
m_name=fName;
}
int QPerson::age()
{ //返回age
return m_age;
}
void QPerson::setAge(int value)
{//设置age
m_age=value;
emit ageChanged(m_age); //发射信号
}
void QPerson::incAge()
{
m_age++;
emit ageChanged(m_age);//发射信号
}
//qmywidget.h文件
#ifndef QMYWIDGET_H
#define QMYWIDGET_H
#include
#include "qperson.h"
namespace Ui {
class QmyWidget;
}
class QmyWidget : public QWidget
{
Q_OBJECT
private:
QPerson *boy;
QPerson *girl;
public:
explicit QmyWidget(QWidget *parent = 0);
~QmyWidget();
private:
Ui::QmyWidget *ui;
signals:
private slots:
//自定义槽函数
void on_ageChanged(int value);
void on_spin_valueChanged(int arg1);
//界面按钮的槽函数
void on_btnClear_clicked();
void on_btnBoyInc_clicked();
void on_btnGirlInc_clicked();
void on_btnClassInfo_clicked();
};
#endif // QMYWIDGET_H
//qmywidget.cpp文件
#include "qmywidget.h"
#include "ui_qmywidget.h"
#include
QmyWidget::QmyWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::QmyWidget)
{//构造函数
ui->setupUi(this);
boy=new QPerson("王小明");
boy->setProperty("score",95);
boy->setProperty("age",10);
boy->setProperty("sex","Boy");//动态属性
// connect(boy,SIGNAL(ageChanged(int)),this,SLOT(on_ageChanged(int)));
connect(boy,&QPerson::ageChanged,this,&QmyWidget::on_ageChanged);
girl=new QPerson("张小丽");
girl->setProperty("score",81);
girl->setProperty("age",20);
girl->setProperty("sex","Girl");//动态属性
connect(girl,&QPerson::ageChanged,this,&QmyWidget::on_ageChanged);
ui->spinBoy->setProperty("isBoy",true); //动态属性
ui->spinGirl->setProperty("isBoy",false);
// 不能使用此形式,因为QSpinBox有两种参数形式的valueChanged()信号
// connect(ui->spinGirl,&QSpinBox::valueChanged,
// this,&QmyWidget::on_spinBoy_valueChanged);
// connect(ui->spinGirl,SIGNAL(valueChanged(int)),
// this,SLOT(on_spin_valueChanged(int)));
connect(ui->spinBoy,SIGNAL(valueChanged(int)),
this,SLOT(on_spin_valueChanged(int)));
}
QmyWidget::~QmyWidget()
{
delete ui;
}
void QmyWidget::on_ageChanged( int value)
{//响应QPerson的ageChanged()信号
Q_UNUSED(value);
QPerson *aPerson = qobject_cast(sender()); //类型投射
QString hisName=aPerson->property("name").toString(); //姓名
// QString hisName=aPerson->name(); //获取姓名,错误
QString hisSex=aPerson->property("sex").toString(); //动态属性
int hisAge=aPerson->age();//通过接口函数获取年龄
// int hisAge=aPerson->property("age").toInt();//通过属性获得年龄
ui->textEdit->appendPlainText(hisName+","+hisSex
+QString::asprintf(",年龄=%d",hisAge));
}
void QmyWidget::on_btnClear_clicked()
{//"清空文本框"按钮
ui->textEdit->clear();
}
void QmyWidget::on_btnBoyInc_clicked()
{//"boy长大一岁"按钮
boy->incAge();
}
void QmyWidget::on_btnGirlInc_clicked()
{//"girl长大一岁"按钮
girl->incAge();
}
//点击控件的增加图标,信号槽会进去两次,不明原因;直接修改值或者通过按钮修改值信号槽仅会进去一次
void QmyWidget::on_spin_valueChanged(int arg1)
{//响应界面上spinBox的valueChanged(int)信号
Q_UNUSED(arg1);
QSpinBox *spinBox = qobject_cast(sender());
if (spinBox->property("isBoy").toBool())
{
boy->setAge(spinBox->value());
//spinBox->blockSignals(true);
}
else
girl->setAge(spinBox->value());
}
void QmyWidget::on_btnClassInfo_clicked()
{//"类的元对象信息"按钮
// const QMetaObject *meta=boy->metaObject();
const QMetaObject *meta=girl->metaObject();
// const QMetaObject *meta=ui->spinBoy->metaObject();
ui->textEdit->clear();
ui->textEdit->appendPlainText("==元对象信息==\n");
ui->textEdit->appendPlainText(QString("类名称:%1\n").arg(meta->className()));
ui->textEdit->appendPlainText("property");
for (int i=meta->propertyOffset();ipropertyCount();i++)
{
const char* propName=meta->property(i).name();
ui->textEdit->appendPlainText(
QString("属性名称=%1,属性值=%2").arg(propName).arg(boy->property(propName).toString()));
}
ui->textEdit->appendPlainText("");
ui->textEdit->appendPlainText("classInfo");
for (int i=meta->classInfoOffset();iclassInfoCount();++i)
{
QMetaClassInfo classInfo=meta->classInfo(i);
ui->textEdit->appendPlainText(
QString("Name=%1; Value=%2").arg(classInfo.name()).arg(classInfo.value()));
}
}
//main()函数
#include "qmywidget.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QmyWidget w;
w.show();
return a.exec();
}