一.属性
1.属性的好处
说到属性(property),你们会想到什么?我会联想到特点,就是一类对象所特有的,在C++中,成员数据就是这个类所特有的。
在C++中为了保证数据安全,一般我们会用到封装,就会把成员数据设置成私有的,但是我们为了能够访问和修改成员数据,我们会定义共有接口。
这样我们就只需要去知道函数的接口名字就可以进行访问和修改了。
那么属性的好处是什么?就是咱们可以不用知道具体的函数接口名称,可以直接用统一的方法进行访问和修改。
有利有弊,弊端是麻烦了程序员,但是造福了使用者。
2.添加属性
属性是属于类的,所以首先咱们来为一个类添加一个属性。
对sources文件右键可以添加类
基类(Base class)一定要选择QObject,这样就可以使用qt的特性
开始在car.h中添加属性
#ifndef CAR_H #define CAR_H #include <QObject> class Car : public QObject { Q_OBJECT Q_PROPERTY(int money READ getMoney WRITE setMoney NOTIFY moneyChanged) public: explicit Car(QObject *parent = nullptr); signals: }; #endif // CAR_H
Q_PROPERTY(int money READ getMoney WRITE setMoney NOTIFY moneyChanged)这句就是添加属性,我这里是为汽车添加了一个价格的属性。
Q_PROPERTY是一个宏,用来添加属性
括号里一共有八个值,下面我来细细剖析
- 第一个值为属性的类型,可以是各种类型
- 第二个值为属性的名字
- READ表示读方法,后面紧跟读方法的函数名
- WRITE表示为写方法,后面紧跟写方法的函数名
- NOTIFY表示通知,是一个信号。
- 注意都是空格隔开
当我们把属性设置好之后,就要开始做具体的实现。
首先先将自定义的信号写好
然后将属性的数据类型加上,还有定义上成员函数跟c++一样
#ifndef CAR_H #define CAR_H #include <QObject> class Car : public QObject { Q_OBJECT Q_PROPERTY(int money READ getMoney WRITE setMoney NOTIFY moneyChanged) public: explicit Car(QObject *parent = nullptr); int getMoney()const;// void setMoney(int money);// signals: void moneyChanged(int money);// private: int m_money;// }; #endif // CAR_H
然后在car.cpp中做具体的实现
#include "car.h" Car::Car(QObject *parent) : QObject(parent) { } int Car::getMoney()const { return m_money; } void Car::setMoney(int money) { m_money=money; emit moneyChanged(money);//如果价钱改变了,我们就手动发出信号 }
3.使用属性
接下来就该去使用属性了,先来回顾一下以前我们怎么去使用成员函数去访问和修改数据。
在mainwindow.h中新加一个数据成员和写一个槽函数
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <car.h>//头文件 QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); public slots: void moneyChanged(int money);//槽函数 private: Ui::MainWindow *ui; Car*car;//定义一个指针来new Car }; #endif // MAINWINDOW_H
在mainwindow.cpp中:
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QDebug> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); car=new Car;//开辟空间 connect(car,&Car::moneyChanged,this,&MainWindow::moneyChanged); car->setMoney(219999); qDebug()<<car->getMoney(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::moneyChanged(int money) { qDebug()<<"价格改动了!现在是:"<<money<<endl; }
运行结果:
这就是咱们以前的通过成员函数访问和修改成员数据,你必须要知道成员方法名。
现在我们来用属性的方式来进行成员数据的读和写。
运行效果:
可以看成,对象的setProperty等同于原来的setMoney,property等同于原来的getMoney.
这样一来我们就不用管成员函数的名字了,只需要知道属性的名字即可
setProperty的第一个参数为属性的名字,只能是字符串,第二个参数的为属性的值,可以是任何类型。
property的参数只需要属性名,toString()是转换成字符串方便打印
二.只读属性
对于属性的读写我们可以自己进行控制下面我们为汽车做一个品牌的属性,只能读,不能写。
首先添加一个属性,READ,WRITE,NOTIFY都是可控的,可以写或者不写。这里不写WRITE,就不能对其进行写操作,也没有传信号。
将相关的添加完
在car.cpp中进行实现
这里我们就应该要想到,只读的话,我们不能进行设置值,因此咱们要对只读的数据进行初始化在构造函数中。
然后在car.cpp中进行实现
在mainwindow.cpp中进行使用,可以看成我们只能读到三无品牌,不能对其进行修改成小米SU7。
当然只写属性也是可以定义的,加上WRITE,不加READ就行,但是我们一般不会这么搞。
就先讲到这里,要锁门了,哈哈哈,属性的其他玩法,我会在下一篇发,好的,再见!