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

QT:核心机制

元对象系统

●该类必须继承自QObject类。
●必须在类定义的私有部分添加Q_OBJECT宏(在类定义时,如果没有指定public或者private关键字,则默认为private)​。
●元对象编译器Meta-ObjectCompiler(MOC)为QObject的子类实现元对象特性提供必要的代码。
提供对象通信机制:信号(Signals)和槽(Slots)。这是一种观察者模式的实现,允许对象之间在不直接引用的情况下进行通信。
运行时类型信息:允许在运行时查询对象的类型信息。
动态属性系统:允许在运行时动态地添加和查询对象的属性。

属性系统

在Qt中,Q_PROPERTY()宏是用于在类中声明属性的。这个宏允许你在Qt的元对象系统中注册一个属性,从而使得该属性可以利用Qt的信号与槽机制、动态属性系统以及Qt Designer等工具进行交互。

Q_PROPERTY()宏通常放在类的私有部分,紧跟在Q_OBJECT宏之后。它接受多个参数,用于定义属性的名称、类型、读写函数(可选)、通知信号(可选)以及属性存储(可选)。

以下是一个Q_PROPERTY()宏的基本用法示例:

class MyClass : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int myProperty READ getMyProperty WRITE setMyProperty NOTIFY myPropertyChanged)

public:
    MyClass(QObject *parent = nullptr) : QObject(parent), m_myProperty(0) {}

    int getMyProperty() const {
        return m_myProperty;
    }

    void setMyProperty(int value) {
        if (m_myProperty != value) {
            m_myProperty = value;
            emit myPropertyChanged(value);
        }
    }

signals:
    void myPropertyChanged(int newValue);

private:
    int m_myProperty;
};

在这个例子中:

int myProperty:定义了属性的类型为int,名称为myProperty。
READ getMyProperty:指定了读取该属性的函数是getMyProperty。
WRITE setMyProperty:指定了写入该属性的函数是setMyProperty。
NOTIFY myPropertyChanged:指定了当属性值改变时应该发出的通知信号是myPropertyChanged。
当你使用Q_PROPERTY()宏声明了一个属性后,你可以通过Qt的反射机制(如QObject::property()和QObject::setProperty())来动态地获取和设置该属性的值。此外,由于属性已经注册到了元对象系统中,因此它还可以与Qt的信号与槽机制、Qt Designer的属性编辑器以及Qt的动画框架等进行交互。

需要注意的是,虽然Q_PROPERTY()宏提供了很大的灵活性,但它也有一些限制。例如,它不支持直接声明为const的属性,因为属性需要能够被读取和写入(或者至少被读取)。此外,虽然你可以为属性指定默认值,但这个默认值只能在对象构造时通过QObject::setProperty()来设置,而不能在Q_PROPERTY()宏中直接指定。

对象树与拥有权

Qt中使用对象树(object tree)来组织和管理所有的QObject类及其子类的对象。当创建一个QObject对象时,如果使用了其他的对象作为其父对象(parent),那么这个对象就会被添加到父对象的children()列表中,这样当父对象被销毁时,这个对象也会被销毁

例子描述
假设我们有一个简单的Qt应用程序,其中包含一个主窗口(MainWindow)和几个子部件,如按钮(QPushButton)和标签(QLabel)。在这个例子中,我们将展示如何使用对象树来组织这些对象。

#include <QApplication>
#include <QMainWindow>
#include <QPushButton>
#include <QLabel>
#include <QVBoxLayout>

class MainWindow : public QMainWindow {
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) {
        QWidget *centralWidget = new QWidget(this); // 创建中心部件,并设置为主窗口的中心部件
        QVBoxLayout *layout = new QVBoxLayout(centralWidget); // 创建垂直布局

        QLabel *label = new QLabel("Hello, Qt!", this); // 创建标签,并设置MainWindow为其父对象(但实际上这里应该设置为centralWidget,下面会修正)
        label->setParent(centralWidget); // 显式设置父对象为centralWidget,以将其添加到布局中
        layout->addWidget(label); // 将标签添加到布局中

        QPushButton *button = new QPushButton("Close", this); // 创建按钮,并错误地设置MainWindow为其父对象(同样应该设置为centralWidget)
        button->setParent(centralWidget); // 修正父对象为centralWidget
        connect(button, &QPushButton::clicked, this, &QMainWindow::close); // 连接按钮的点击信号到主窗口的关闭槽
        layout->addWidget(button); // 将按钮添加到布局中

        setCentralWidget(centralWidget); // 设置中心部件
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    MainWindow mainWindow; // 创建主窗口对象(在栈上分配内存,不需要手动delete)
    mainWindow.show(); // 显示主窗口

    return app.exec(); // 进入Qt的事件循环
}

说明
父对象设置:在上面的代码中,虽然标签(QLabel)和按钮(QPushButton)最初被错误地设置为以MainWindow为父对象,但通过调用setParent(centralWidget)进行了修正。实际上,在Qt中,通常将布局或容器部件(如QWidget)设置为子部件的父对象,以便更好地管理它们的生命周期和布局。
对象树结构:在这个例子中,MainWindow是顶层对象(没有父对象),而centralWidget是MainWindow的子对象。标签和按钮则是centralWidget的子对象。这样,就形成了一个对象树结构。
内存管理:当MainWindow被销毁时(例如,当用户关闭主窗口时),由于对象树机制,centralWidget及其所有子对象(包括标签和按钮)也会被自动销毁。这简化了内存管理,并防止了内存泄漏。
信号与槽:在这个例子中,还展示了如何使用Qt的信号与槽机制来连接按钮的点击信号到主窗口的关闭槽。这也是Qt对象模型的一个重要特性。


http://www.kler.cn/a/421194.html

相关文章:

  • 【论文复现】隐式神经网络实现低光照图像增强
  • 自然语言处理:基于BERT预训练模型的中文命名实体识别(使用PyTorch)
  • 数据结构4——栈和队列
  • 【C语言】结构体(四)
  • 大数据-240 离线数仓 - 广告业务 测试 ADS层数据加载 DataX数据导出到 MySQL
  • OD C卷 - 实现 【手机App防沉迷系统】
  • 量化交易系统开发-实时行情自动化交易-8.3.开拓者TBQuant平台
  • 精通 Python 网络安全(二)
  • mysql数据库之三范式
  • week 10 - Database: Normalisation
  • win11 多任务 贴靠 bug:左右两窗口贴靠时拖动中间的对齐条后,资源管理器有概率卡死
  • 使用API管理Dynadot域名,设置默认域名服务器ip信息
  • Spring Boot Actuator未授权访问漏洞处理
  • 详解Vue设计模式
  • 基于SpringBoot和PostGIS的云南与缅甸的千里边境线实战
  • hadoop环境配置-创建hadoop用户+更新apt+安装SSH+配置Java环境
  • SpringSecurity6从入门到实战之SecurityContextHolder详解
  • 做SOL交易机器人拆解步骤,其实没有那么复杂。
  • VMware tool安装
  • 3248. 矩阵中的蛇
  • VScode离线下载扩展安装
  • Socket编程-udp
  • 详解版本控制工作原理及优势,常见的版本控制系统对比(HelixCore、Git、SVN等)
  • 【网络安全】网络加密原理 与 无线网络安全 链路加密
  • 深入详解人工智能入门数学基础:理解向量、矩阵及导数的概念
  • 关于数据库数据国际化方案