qt5 qml界面项目会用到的一些qt函数,和前后端通信的一些逻辑

qRegisterMetaType

主要用于在 Qt 的元对象系统中注册自定义类型,以便这些类型能够用于信号和槽机制、QVariant 以及跨线程通信等场景。

struct MyData {
    int id;
    QString name;
};
Q_DECLARE_METATYPE(MyData); // 声明元类型

// 在使用前注册:
qRegisterMetaType<MyData>("MyData");

// 之后可以用于信号槽:
QObject::connect(sender, &Sender::mySignal, receiver, &Receiver::mySlot);

connect()

连接信号和槽,实现对象通信。
用法:connect(发信对象,信号,接受槽对象,槽函数)
connect(sender, &Class::Signal, receiver, &Class::Slot)

QMetaObject::Connection QObject::connect(
    const QObject *sender,        // 发送信号的对象
    const char *signal,           // 信号(SIGNAL() 宏或 &Class::Signal)
    const QObject *receiver,      // 接收槽的对象
    const char *method,           // 槽函数(SLOT() 宏或 &Class::Slot)
    Qt::ConnectionType type = Qt::AutoConnection
);

在这里插入图片描述

QAbstractListModel

任何需要频繁更新的列表,用法如下:

1. QAbstractListModel用法结构

QAbstractListModel基本用法(C++ 端实现)

(1)创建自定义模型类

// MyListModel.h
#include <QAbstractListModel>
#include <QStringList>

class MyListModel : public QAbstractListModel {
    Q_OBJECT
public:
    explicit MyListModel(QObject *parent = nullptr);

    // 必须重写的函数
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    QVariant data(const QModelIndex &index, int role) const override;

    // 可选:定义 Role 名称(供 QML 使用)
    QHash<int, QByteArray> roleNames() const override;

    // 自定义方法:修改数据
    Q_INVOKABLE void addItem(const QString &text);
    Q_INVOKABLE void removeItem(int index);

private:
    QStringList m_data; // 实际数据存储
};

(2)实现模型逻辑

// MyListModel.cpp
MyListModel::MyListModel(QObject *parent) : QAbstractListModel(parent) {
    // 初始化数据
    m_data << "Apple" << "Banana" << "Orange";
}

// 重载
int MyListModel::rowCount(const QModelIndex &parent) const {
    Q_UNUSED(parent);
    return m_data.size();
}

// 重载
QVariant MyListModel::data(const QModelIndex &index, int role) const {
    if (!index.isValid() || index.row() >= m_data.size())
        return QVariant();

    // 根据 Role 返回不同数据
    if (role == Qt::DisplayRole || role == TitleRole)
        return m_data.at(index.row());

    return QVariant();
}

// 重载
QHash<int, QByteArray> MyListModel::roleNames() const {
    return {
        {TitleRole, "title"} // QML 中通过 model.title 访问
    };
}

void MyListModel::addItem(const QString &text) {
    beginInsertRows(QModelIndex(), rowCount(), rowCount());
    m_data.append(text);
    endInsertRows();
}

void MyListModel::removeItem(int index) {
    if (index < 0 || index >= m_data.size()) return;

    beginRemoveRows(QModelIndex(), index, index);
    m_data.removeAt(index);
    endRemoveRows();
}

(3)注册模型到QML

// main.cpp
#include <QQmlApplicationEngine>
#include <QQmlContext>

qmlRegisterType<MyListModel>("CustomModels", 1, 0, "MyListModel");

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

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

QAbstractListModel在QML 端使用

**(1)基本 ListView 绑定 **

// main.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
import CustomModels 1.0

ListView {
    width: 200; height: 300
    model: MyListModel { id: myModel }
    delegate: Text { 
        text: model.title // 对应 roleNames() 中的 "title"
    }
}

(2)动态操作模型

Column {
    Button {
        text: "Add Item"
        onClicked: myModel.addItem("New Item " + Math.random())
    }
    Button {
        text: "Remove First"
        onClicked: myModel.removeItem(0)
    }
}

2. QAbstractListModel的QModelIndex

关键方法

方法说明
row()返回行号(0-based)
column()返回列号(0-based)
parent()返回父索引
data(int role)获取指定角色的数据
sibling()获取同级索引
isValid()检查索引是否有效

核心属性

属性/方法类型说明示例
row()int获取索引指向的行号(从0开始)index.row() → 2
column()int获取索引指向的列号(从0开始)index.column() → 1
parent()QModelIndex获取父级索引(顶层返回空索引)index.parent().isValid()false
internalId()quintptr内部标识符(用于自定义模型)index.internalId() → 12345
internalPointer()void*指向关联数据的指针(高级用法)static_cast<Item*>(index.internalPointer())
model()const QAbstractItemModel*获取所属模型对象index.model()->rowCount()

QtConcurrent 详解 (异步执行)

QtConcurrent 是 Qt 提供的高级 API,用于简化多线程编程,无需直接管理 QThread。

1. 核心功能

  • 并行计算:自动利用多核处理器
  • 简化线程管理:无需显式创建线程
  • 安全的数据访问:通过 Future/Promise 模式处理结果
  • 与 Qt 事件循环集成:支持信号槽通知

2. 主要模块

2.1 并行算法

// 并行映射
QList<int> list = {1, 2, 3, 4};
QFuture<void> future = QtConcurrent::map(list, [](int &x){ x *= 2; });

// 并行过滤
QFuture<QList<int>> filtered = QtConcurrent::filtered(list, [](int x){ return x > 2; });

// 并行归约
int sum = QtConcurrent::blockingReduced(list, std::plus<int>());

2.2 异步算法

// 运行函数并返回 Future
QFuture<QString> future = QtConcurrent::run([](){
    return QImage("large.png").scaled(1000, 1000).save("thumbnail.jpg");
});

// 获取结果(阻塞方式)
QString result = future.result();

// 非阻塞方式获取结果
QFutureWatcher<QString> *watcher = new QFutureWatcher<QString>();
connect(watcher, &QFutureWatcher<QString>::finished, [=](){
    qDebug() << "Result:" << watcher->result();
});
watcher->setFuture(future);

QFuture 深度解析

1. 核心概念

QFuture<T> 是 Qt 提供的异步计算结果容器,代表未来将会可用的数据。它与 QtConcurrentQPromise 配合使用,实现非阻塞的多线程编程。

2. 关键特性

  • 异步结果获取:不阻塞主线程
  • 进度跟踪:支持任务进度监控
  • 取消支持:可中断正在执行的任务
  • 多结果处理:适用于返回多个值的场景(如 mapped()

3. 核心方法

状态检查

方法说明
isStarted()任务是否已开始
isFinished()任务是否完成
isCanceled()任务是否被取消
isRunning()任务是否正在运行

结果获取

方法说明
result()阻塞等待并返回结果
resultAt(index)获取多结果中的指定项
results()返回所有结果的列表(Qt 6+)

控制方法

方法说明
cancel()尝试取消任务
pause()暂停任务(需任务支持)
resume()恢复暂停的任务

4. 基本使用流程

创建 Future

// 通过 QtConcurrent 创建
QFuture<int> future = QtConcurrent::run([](){
    QThread::sleep(2);
    return 42;
});

// 通过 QPromise 创建(Qt 6+)
QPromise<int> promise;
QFuture<int> manualFuture = promise.future();

Qt Q_PROPERTY 详解

1. 核心作用

Q_PROPERTY 是 Qt 元对象系统的核心宏之一,用于声明类的属性,实现以下功能:

  • QML 绑定:支持属性与 QML 的双向绑定
  • 动态访问:通过 property()setProperty() 方法操作
  • 自动通知:属性变更触发信号通知
  • 代码生成:由 moc 生成元对象代码

2. 基本语法结构

Q_PROPERTY(type name
           READ getFunction
           WRITE setFunction
           NOTIFY notifySignal
           RESET resetFunction
           DESIGNABLE bool
           SCRIPTABLE bool
           STORED bool
           USER bool)

因此getFunction setFunction函数已经算是被声明了,需要进一步去定义它。

3. 必须参数详解

参数说明示例
type属性数据类型QString, int, bool
name属性名称text, isActive
READ获取属性值的成员函数QString text() const

4. 可选参数说明

参数作用典型用法
WRITE设置属性值的槽函数void setText(const QString&)
NOTIFY属性变更信号void textChanged()
RESET重置为默认值的函数void resetText()
DESIGNABLEQt Designer 可见性DESIGNABLE true
STORED序列化时是否保存STORED true

QVector 深度解析

1. 基本概念

QVector<T> 是 Qt 提供的动态数组容器类(Qt 6 后改名为 QList<T>),提供高效的随机访问和尾部操作。
类似于python中的list列表。

2. 核心特性

  • 动态扩容:自动管理内存
  • 值语义:隐式共享(Copy-On-Write)
  • STL兼容:提供标准迭代器
  • 类型安全:模板类设计

3. 主要操作(时间复杂度)

基本操作

操作时间复杂度示例
随机访问O(1)vec[0]
尾部追加平摊 O(1)vec.append(x)
头部插入O(n)vec.prepend(x)
中间插入O(n)vec.insert(2, x)
查找O(n)vec.contains(x)

容量管理

方法说明
resize(n)调整元素数量
reserve(n)预分配内存
capacity()返回已分配空间
squeeze()释放多余内存

4. 与 std::vector 对比

特性QVectorstd::vector
内存策略隐式共享直接拷贝
接口风格Qt风格STL风格
性能侧重快速遍历侧重随机访问
线程安全只读操作线程安全需要手动同步

5. 基本使用示例

创建和初始化

// 空向量
QVector<int> vec1; 

// 指定大小初始化
QVector<QString> vec2(10, "default"); 

// 列表初始化
QVector<double> vec3 = {1.1, 2.2, 3.3};

QHash

哈希表,就是python中的字典

MVC框架

组件职责类比
Model(模型)数据管理和业务逻辑仓库管理员
View(视图)数据展示和用户界面商店橱窗
Controller(控制器)处理用户输入和协调交互售货员

在这里插入图片描述

qmlRegister和setContextProperty

Model定义好后,需要注册,Qt qml有两个注册函数:qmlRegisterType 和 qmlRegisterSingletonType

qmlRegister

特性qmlRegisterTypeqmlRegisterSingletonType
实例化方式每次 QML 声明时创建新实例全局唯一实例
典型用途可复用的 UI 组件、数据模型全局服务、工具类、配置管理
QML 中访问方式通过声明元素(如 MyItem {}直接通过类型名(如 MySingleton.method()
内存管理由 QML 引擎管理通常需手动管理(除非使用智能指针)
线程安全性实例独立,需自行处理线程安全单例需考虑线程安全
qmlRegisterSingletonType<SystemModel>("SystemModel", 1, 0, "SystemModel",
                                               [](QQmlEngine *engine, QJSEngine *jsEngine) -> QObject* {
                                                   (void)engine;
                                                   (void)jsEngine;
                                                   return &SYSTEM_MODEL;
                                               }
                                               );
                                               
qmlRegisterType<NetworkManager>("QtNetworkManager", 1, 0, "NetworkManager");

注册完毕后,qml就能识别你的model文件了。
这种是模块化的注册,所以需要在对应的.qml文件里导入
import SystemModel 1.0
就能调用systemmodel里的函数了

setContextProperty

// setContextProperty 方式
engine.rootContext()->setContextProperty("confirmPopupModel", &CONFIRM_POPUP_MODEL);

这种是全局性的注册,qml端不用导入可以直接调用

// QML中直接使用,无需导入
Rectangle {
    Component.onCompleted: {
        confirmPopupModel.show() // 直接访问
    }
}

区别

在这里插入图片描述

传输修改

model

信号直接来自qml文件,同时会经过model文件的修饰和处理,然后发出去。
在model中发送修改信号到Moonraker中,在modelhandletask.cpp的initConnection里添加:

// 添加了这一行就能实现控制了  
    // sigEditTargetLeftNozzleTemper 是 CameraManagerModel的 signal里的信号
    // onHandleLeftTemperature 是 ModelHandleTask的槽函数,该函数需要在本页根据 Moonraker 里的json类型进行定义
    connect(&CAMERA_MANAGER_MODEL, &CameraManagerModel::sigEditTargetLeftNozzleTemper, this, &ModelHandleTask::onHandleLeftTemperature, Qt::QueuedConnection);

message

在WebSocketThread.cpp的初始化函数中将moonraker的信息通过textMessageReceived函数传给websocketThread的onreciveMessage;

// WebSocketThread.cpp
connect(_webClient.get(), &QWebSocket::textMessageReceived, this, &WebSocketThread::onReciveMessage);

// 立刻激发出去
void WebSocketThread::onReciveMessage(const QString &message)
{
    // qDebug() << "WebSocketThread: onWebsocketRecive" << message;
    emit sigReciveMessage(message);
}

在mainctrl.cpp中再调用websocketThread的sigReciveMessage信号,修饰一番,再传入到MessageHandleTask的信号槽onReciveMessage中。
但是不知道为什么信号对象由_webClient转变成了_webClientTask.

// mainctrl.cpp
connect(_webClientTask.get(), &WebSocketThread::sigReciveMessage, _messageTask.get(), &MessageHandleTask::onReciveMessage, Qt::QueuedConnection);

MessagehandleTask中的onReciveMessage是专门处理Moonraker信息并且分配到各个model中,让model去刷新界面

至此,通信流程结束。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值