当前位置: 首页 > news >正文

江苏天宇建设集团官方网站网站建设与网站制作

江苏天宇建设集团官方网站,网站建设与网站制作,番禺区住房和建设局物业网站,济南优化官网公司Qt 属性系统是 Qt 框架中一个非常核心和强大的部分#xff0c;它提供了一种标准化的方法来访问对象的属性。这一系统不仅使得开发者能够以一致的方式处理各种数据类型#xff0c;还为动态属性的管理提供了支持#xff0c;并与 Qt 的元对象系统紧密集成。在这篇文章中#x…Qt 属性系统是 Qt 框架中一个非常核心和强大的部分它提供了一种标准化的方法来访问对象的属性。这一系统不仅使得开发者能够以一致的方式处理各种数据类型还为动态属性的管理提供了支持并与 Qt 的元对象系统紧密集成。在这篇文章中我们将详细介绍 Qt 属性系统的概念、实现机制和使用方式以及它如何帮助开发者提升应用程序的灵活性和可维护性。 Q_PROPERTY 声明属性的类必须要继承QObject并且使用Q_OBJECT宏然后通过Q_PROPERTY宏来声明属性。 源码解释 Q_PROPERTY(type name(READ getFunction [WRITE setFunction] |MEMBER memberName [(READ getFunction | WRITE setFunction)])[RESET resetFunction][NOTIFY notifySignal][REVISION int | REVISION(int[, int])][DESIGNABLE bool][SCRIPTABLE bool][STORED bool][USER bool][CONSTANT][FINAL][REQUIRED])基本结构 type属性的数据类型支持以下类型 Qt内建类型常见的Qt数据类型如QString、QDate、QTime、QDateTime、QUrl、QList、QMap、QStringList、QChar、QByteArray等。标准C类型int、bool、double、float、char*等。枚举类型自定义类型自定义的类也可以作为属性的类型但是要满足以下条件 类必须被Qt的元对象系统所知晓这通常意味着类需要使用Q_DECLARE_METATYPE宏声明。类需要提供公共的构造函数、拷贝构造函数和赋值运算符以便Qt能够在内部处理属性的复制和赋值。如果要通过QVariant进行存储或传递类必须注册到Qt的类型系统中使用qRegisterMetaTypeClassName()。 name属性的名称 注意这里的name和具体的成员变量名可以不同因为Q_PROPERTY声明的属性不是具体的成员属性是用来关联对应某个成员对象的。 访问函数 READREAD访问器函数即读取属性值的函数。函数的返回值必须是属性对应类型或对该类型的const引用函数体必须带const修饰。函数示例如下 type getNameFunction() const;const type getNameFunction() const; WRITEWRITE访问器函数即修改属性值的函数。函数的返回值必须是void类型并且只接受一个参数可以是属性对应的类型也可以是指向该类型的指针或引用。函数示例如下 void setNameFunction(type val);void setNameFunction(const type val); MEMBER直接指定类中的成员变量作为属性的存储代替使用单独的读写方法。可以与READ或WRITE搭配使用来覆盖默认的成员访问。 可选修饰符 RESET指定一个函数用于重置属性到默认的初始状态。通常不带参数没有返回值。NOTIFY指定当属性值改变时要发出的信号。这在绑定和数据驱动的界面更新中非常有用。REVISION用于版本控制指明属性从哪个Qt版本开始可用。这主要用于与QML集成时的版本控制。DESIGNABLE指定属性是否应该在Qt设计器中显示默认为true。SCRIPTABLE指定属性是否可以通过脚本访问默认为true。STORED指明属性是否应该被序列号默认为true。如果属性是计算出来的并不需要存储可以设置为false。USER指明这个属性是否被指定为该类的面向用户的属性或用户可编辑的属性。通常每个类只有一个USER属性默认为false。CONSTANT标记属性为常量一旦在构造函数中设置后不能改变。常用于只读的配置值。FINAL指明这个属性在派生类中不能被重写。REQUIRED属性的存在表明该属性应由该类的用户设置。这不是由 moc 强制执行的并且对于暴露于 QML 的类来说最有用。在 QML 中除非设置了所有必需属性否则无法实例化具有必需属性的类。 使用示例 注意 使用READ和WRITE两个访问器函数在未指定MEMBER时需要显式定义在指定MEMBER时可以不用显式定义READ和WRITE两个访问器函数READ和WRITE两个访问器函数主要的作用不是显式调用相应的函数而是通过对象的property()和setProperty()来调用 只读属性 class Data : public QObject {Q_OBJECTQ_PROPERTY(QString name READ name FINAL) public:explicit Data(QObject* parent nullptr): QObject(parent){}QString name() const{return m_name;}private:QString m_name { Data }; };int main(int argc, char* argv[]) {QCoreApplication a(argc, argv);Data data;// 使用 property() 来获取属性值qDebug() Initial name: data.property(name).toString();// 使用 setProperty() 来修改属性值data.setProperty(name, Updated Name);qDebug() Updated name: data.property(name).toString();return a.exec(); }输出结果 Initial name: Data Updated name: Data可读写属性 class Data : public QObject {Q_OBJECTQ_PROPERTY(QString name READ name WRITE setName FINAL) public:explicit Data(QObject* parent nullptr): QObject(parent){}QString name() const{return m_name;}void setName(const QString name){if (name ! m_name)m_name name;}private:QString m_name { Data }; };int main(int argc, char* argv[]) {QCoreApplication a(argc, argv);Data data;// 使用 property() 来获取属性值qDebug() Initial name: data.property(name).toString();// 使用 setProperty() 来修改属性值data.setProperty(name, Updated Name);qDebug() Updated name: data.property(name).toString();return a.exec(); }输出结果 Initial name: Data Updated name: Updated NameMEMBER关键字 class Data : public QObject {Q_OBJECTQ_PROPERTY(QString name MEMBER m_name FINAL) public:explicit Data(QObject* parent nullptr): QObject(parent){}private:QString m_name { Data }; };int main(int argc, char* argv[]) {QCoreApplication a(argc, argv);Data data;// 使用 property() 来获取属性值qDebug() Initial name: data.property(name).toString();// 使用 setProperty() 来修改属性值data.setProperty(name, Updated Name);qDebug() Updated name: data.property(name).toString();return a.exec(); }输出结果 Initial name: Data Updated name: Updated Name使用MEMBER关键字时用户无法通过实例对象显式调用getter和setter函数只能通过property()和setProperty()来获取和设置。 NOTIFY关键字的使用 class Data : public QObject {Q_OBJECTQ_PROPERTY(QString name MEMBER m_name NOTIFY nameChanged FINAL) public:explicit Data(QObject* parent nullptr): QObject(parent){}signals:void nameChanged(const QString name);private:QString m_name { Data }; };int main(int argc, char* argv[]) {QCoreApplication a(argc, argv);Data data;QObject::connect(data, Data::nameChanged, [data](const QString name) {qDebug() nameChanged: data.property(name);});// 使用 property() 来获取属性值qDebug() Initial name: data.property(name).toString();// 使用 setProperty() 来修改属性值data.setProperty(name, Updated Name);qDebug() Updated name: data.property(name).toString();return a.exec(); }输出结果 Initial name: Data nameChanged: QVariant(QString, Updated Name) Updated name: Updated Name属性系统的主要应用场景 C和QML交互 首先我们需要定义一个包含可观察属性的C类。此类将发出属性变化的信号QML界面将响应这些信号更新显示。CppBackend.h #ifndef CPPBACKEND_H #define CPPBACKEND_H#include QObject #include QStringclass CppBackend : public QObject {Q_OBJECTQ_PROPERTY(QString message READ message WRITE setMessage NOTIFY messageChanged)public:explicit CppBackend(QObject *parent nullptr) : QObject(parent), m_message(Hello from C!) {}QString message() const { return m_message; }public slots:void setMessage(const QString message) {if (m_message ! message) {m_message message;emit messageChanged();}}signals:void messageChanged();private:QString m_message; };#endif // CPPBACKEND_H接下来我们创建一个QML文件来显示message属性并提供一个按钮来改变它。main.qml import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15Window {width: 640height: 480visible: truetitle: qsTr(Hello World)Column {anchors.centerIn: parentspacing: 20Text {id: displayTexttext: backend.messagefont.pointSize: 20}Button {text: Change MessageonClicked: {backend.message Updated by QML!}}} }在主程序中我们将注册后端对象为QML可访问并加载QML文件。main.cpp #include CppBackend.h #include QGuiApplication #include QQmlApplicationEngine #include QQmlContextint main(int argc, char* argv[]) { #if QT_VERSION QT_VERSION_CHECK(6, 0, 0)QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #endifQGuiApplication app(argc, argv);QQmlApplicationEngine engine;CppBackend backend;engine.rootContext()-setContextProperty(backend, backend);const QUrl url(QStringLiteral(qrc:/main.qml));QObject::connect(engine,QQmlApplicationEngine::objectCreated,app,[url](QObject* obj, const QUrl objUrl) {if (!obj url objUrl)QCoreApplication::exit(-1);},Qt::QueuedConnection);engine.load(url);return app.exec(); }属性树形控件 属性树形控件的类虽然已经被移除但QtCreator还是在使用的可以通过Qt的源码查找qtpropertybrowser。展示使用的代码TestData1.h #ifndef TESTDATA1_H #define TESTDATA1_H#include QColor #include QObjectclass TestData1 : public QObject {Q_OBJECTQ_PROPERTY(int count READ count WRITE setCount NOTIFY countChanged FINAL)Q_PROPERTY(QColor bkColor READ bkColor WRITE setBkColor NOTIFY bkColorChanged FINAL)Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged FINAL) public:explicit TestData1(QObject* parent nullptr): QObject(parent){}int count() const { return m_count; }void setCount(int value){if (value ! m_count) {m_count value;emit countChanged(m_count);}}QColor bkColor() const { return m_bkColor; }void setBkColor(const QColor color){if (color ! m_bkColor) {m_bkColor color;emit bkColorChanged(m_bkColor);}}QString name() const { return m_name; }void setName(const QString value){if (value ! m_name) {m_name value;emit nameChanged(m_name);}}signals:void countChanged(int value);void bkColorChanged(const QColor color);void nameChanged(const QString name);private:int m_count { 1 };QColor m_bkColor { Qt::black };QString m_name { TestData }; };#endif // TESTDATA1_HTestData2.h #ifndef TESTDATA2_H #define TESTDATA2_H#include QColor #include QObjectclass TestData2 : public QObject {Q_OBJECTQ_PROPERTY(int number READ count WRITE setCount NOTIFY countChanged FINAL)Q_PROPERTY(QColor bkColor READ bkColor WRITE setBkColor NOTIFY bkColorChanged FINAL)Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged FINAL) public:explicit TestData2(QObject* parent nullptr): QObject(parent){}int count() const { return m_number; }void setCount(int value){if (value ! m_number) {m_number value;emit countChanged(m_number);}}QColor bkColor() const { return m_bkColor; }void setBkColor(const QColor color){if (color ! m_bkColor) {m_bkColor color;emit bkColorChanged(m_bkColor);}}QString name() const { return m_name; }void setName(const QString value){if (value ! m_name) {m_name value;emit nameChanged(m_name);}}signals:void countChanged(int value);void bkColorChanged(const QColor color);void nameChanged(const QString name);private:int m_number { 99 };QColor m_bkColor { Qt::blue };QString m_name { TestData2 }; }; #endif // TESTDATA2_Hwidget.h #ifndef WIDGET_H #define WIDGET_H#include qtpropertybrowser/qteditorfactory.h #include qtpropertybrowser/qttreepropertybrowser.h #include qtpropertybrowser/qtvariantproperty.h #include testdata1.h #include testdata2.h #include QListWidgetItem #include QWidgetQT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget* parent nullptr);~Widget();private slots:void on_listWidget_currentItemChanged(QListWidgetItem* current, QListWidgetItem* previous);protected:void updateProperties(QObject* selectedObject);private:Ui::Widget* ui;QtVariantPropertyManager* m_variantManager;QtVariantEditorFactory* m_variantFactory;TestData1 m_data1;TestData1 m_data1_2;TestData2 m_data2;TestData2 m_data2_2; }; #endif // WIDGET_Hwidget.cpp #include widget.h #include ./ui_widget.h #include QMetaPropertyWidget::Widget(QWidget* parent): QWidget(parent), ui(new Ui::Widget), m_variantManager(new QtVariantPropertyManager(this)), m_variantFactory(new QtVariantEditorFactory(this)) {ui-setupUi(this);m_data1.setName(TestData1);m_data1.setBkColor(Qt::red);m_data1_2.setName(TestData1_2);m_data1_2.setBkColor(Qt::yellow);m_data2.setCount(60);ui-widget-setFactoryForManager(m_variantManager, m_variantFactory);QtVariantProperty* item m_variantManager-addProperty(QVariant::Double, 透明度);item-setValue(0.5);ui-widget-addProperty(item); }Widget::~Widget() {delete ui; }void Widget::on_listWidget_currentItemChanged(QListWidgetItem* current, QListWidgetItem* previous) {static int index 0;int i index % 4;if (i 0)updateProperties(m_data1);else if (i 1)updateProperties(m_data1_2);else if (i 2)updateProperties(m_data2);elseupdateProperties(m_data2_2);index; }void Widget::updateProperties(QObject* selectedObject) {ui-widget-clear();auto metaObj selectedObject-metaObject();for (int i 0; i metaObj-propertyCount(); i) {auto propertyObj metaObj-property(i);auto propertyName propertyObj.name();auto propertyValue selectedObject-property(propertyName);auto item m_variantManager-addProperty(propertyValue.type(), propertyName);item-setValue(propertyValue);ui-widget-addProperty(item);connect(m_variantManager, QtVariantPropertyManager::valueChanged,this, [selectedObject](QtProperty* prop, const QVariant value) {selectedObject-setProperty(prop-propertyName().toStdString().c_str(), value);});} }注意 ui-widget就是QtTreePropertyBrowser类。 效果 总结 属性系统说到底就是建立在类的成员变量之上并通过标准化的接口getter和setter以及元对象系统来增强这些成员的功能。在很多UI和数据进行交互的时候我们通常可以通过属性系统提供的标准化接口来实现因为其带来以下好处 一致性和易用性 提供一个统一的方法来访问和修改对象的属性这意味着无论你在哪里或如何使用这些对象访问和修改属性的方式总是相同的。这种一致性减少了学习和使用不同对象时的认知负担使得开发更直观同时也减少了代码中可能出现的错误。 封装和数据保护 通过标准化的 getter 和 setter 方法来访问和修改数据这增强了封装性保护了数据不被非法访问和修改。封装是面向对象编程中的一个核心概念它隐藏了对象的内部状态和实现细节只暴露有限的接口与外界交互。 解耦和模块化 标准化接口促进了解耦和模块化设计。开发者可以更轻松地替换或修改内部实现而不影响使用这些对象的代码。这是因为外部代码依赖于接口而非具体实现从而使得整个系统更加灵活和可维护。 自动化工具和库的集成 标准化的属性接口使得自动化工具如 GUI 设计器和其他库如序列化库、数据库映射工具能够更容易地与你的代码集成。例如一个自动化工具可以通过反射机制查找所有属性并允许用户在图形界面中配置它们。 动态性和反射能力 Qt 的元对象系统依赖于标准化的属性接口来支持反射即在运行时查询和操作对象的能力。这不仅有助于开发各种动态特性如动态数据绑定和脚本集成也使得开发者能够编写通用代码来处理不同类型的对象。 跨语言和平台兼容性 标准化接口简化了在不同编程语言和平台间的对象交互。由于接口提供了清晰定义的交互点因此可以更容易地将 Qt 应用与其他系统集成或者在不同平台间迁移应用。
http://www.w-s-a.com/news/937393/

相关文章:

  • 天猫网站建设的目标是什么seo有些什么关键词
  • 网站前端建设都需要什么莱芜信息港网页
  • 如何做360网站优化网站建设培训教程新手入门到精通
  • 做网站有的浏览器怎么做网站网站赚钱
  • 织梦 做网站 教程百度登录个人中心官网
  • ftp怎么修改网站wordpress分享积分
  • 营销策划方案的步骤西安关键词优化软件
  • 南宁自己的网站移动互联网技术学什么
  • 2017湖北建设教育协会网站自己接单做网站
  • 定制网站建设制作h5网站要多久
  • 泰安中呼网站建设有限公司 概况个人网站的设计与实现参考文献
  • 圣诞节网站怎么做怎么获取网站的图片
  • 想找个人做网站音乐网站建设教程视频教程
  • 网站收录一键提交阿里巴巴做网站多少钱
  • 怎么做网站投放广告商务网站建设实训报告
  • 服装代销的网站源码国内电子商务网站有哪些
  • qq空间怎么做网站做企业平台的网站有哪些
  • 网站的优缺点wordpress手机适配模板中文
  • 福州网站建设H5广告公司简介简短
  • 网站404页面的作用app开发郑州
  • 亚马逊中国网站建设目标网站建设的策划
  • 林州网站建设服务徐州网站建设
  • 如何检测网站死链景德镇网站建设哪家好
  • 旅游网站开发目标天津专业做网站公司
  • 名者观看网站快手小程序
  • 网络架构扁平化windows优化大师好不好
  • 安康养老院收费价格表兰州seo整站优化服务商
  • 网站开发技术方案模板无锡网站建设推荐
  • 自助建站系统注册三维家3d设计软件免费
  • 做seo网站标题重要吗郑州众诚建设监理有限公司网站