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

【CXX-Qt】2.5 继承

某些 Qt API 要求你从抽象基类中重写某些方法,例如 QAbstractItemModel。

为了支持直接从 Rust 中创建这样的子类,CXX-Qt 提供了多种辅助工具。

某些基类可能需要特殊的构造参数。这可以通过使用自定义构造函数来实现。

访问基类方法

要在 Rust 中访问基类的方法,请使用 #[inherit] 宏。它可以放在 #[cxx_qt::bridge] 中的 extern “RustQt” 块中的函数前面。

extern "RustQt" {
    #[qobject]
    #[base = "QAbstractListModel"]
    #[qml_element]
    #[qproperty(State, state)]
    type CustomBaseClass = super::CustomBaseClassRust;
}

// 为基类(QAbstractItemModel)的 C++ 函数创建 Rust 绑定
extern "RustQt" {
    /// 从基类继承的 beginInsertRows 方法
    #[inherit]
    #[cxx_name = "beginInsertRows"]
    unsafe fn begin_insert_rows(
        self: Pin<&mut CustomBaseClass>,
        parent: &QModelIndex,
        first: i32,
        last: i32,
    );
    /// 从基类继承的 endInsertRows 方法
    #[inherit]
    #[cxx_name = "endInsertRows"]
    unsafe fn end_insert_rows(self: Pin<&mut CustomBaseClass>);

    /// 从基类继承的 beginRemoveRows 方法
    #[inherit]
    #[cxx_name = "beginRemoveRows"]
    unsafe fn begin_remove_rows(
        self: Pin<&mut CustomBaseClass>,
        parent: &QModelIndex,
        first: i32,
        last: i32,
    );
    /// 从基类继承的 endRemoveRows 方法
    #[inherit]
    #[cxx_name = "endRemoveRows"]
    unsafe fn end_remove_rows(self: Pin<&mut CustomBaseClass>);

    /// 从基类继承的 beginResetModel 方法
    #[inherit]
    #[cxx_name = "beginResetModel"]
    unsafe fn begin_reset_model(self: Pin<&mut CustomBaseClass>);
    /// 从基类继承的 endResetModel 方法
    #[inherit]
    #[cxx_name = "endResetModel"]
    unsafe fn end_reset_model(self: Pin<&mut CustomBaseClass>);
}

unsafe extern "RustQt" {
    /// 清除 QAbstractListModel 中的行
    #[qinvokable]
    pub fn clear(self: Pin<&mut CustomBaseClass>);
}

impl qobject::CustomBaseClass {
    /// 清除 QAbstractListModel 中的行
    pub fn clear(mut self: Pin<&mut Self>) {
        unsafe {
            self.as_mut().begin_reset_model();
            self.as_mut().rust_mut().id = 0;
            self.as_mut().rust_mut().vector.clear();
            self.as_mut().end_reset_model();
        }
    }
}

完整示例

这段代码实现了一个 QAbstractListModel 子类。为此,Rust 中实现的 clear 方法需要调用基类中的 beginResetModel 及相关方法,这些方法通过使用 #[inherit] 来访问。有关特定子类化要求的更多详细信息,请参阅 Qt 文档。

类似于 CXX,extern “RustQt” 块中的方法可以使用 #[inherit] 属性标记,并且对可使用的类型有相同的限制。此外,self 类型必须是 self: Pin<&mut qobject::T> 或 self: &qobject::T,其中 qobject::T 必须引用在 #[cxx_qt::bridge] 中用 #[qobject] 标记的 QObject。

如果 Rust 名称应与 C++ 方法名称不同(例如,由于 snake_case 与 camelCase 的差异),请使用 #[cxx_name = “myFunctionName”] 或 #[rust_name = “my_function_name”] 属性。

#[inherit]` 也可以用于 `extern RustQt` 块中存在于基类上的信号。

重写基类方法

CXX-Qt 允许生成具有实现继承所需的 C++ 修饰符的可调用方法。这样,方法可以被重写、声明为 virtual 或 final。

C++ 关键字 CXX-Qt 属性
override #[cxx_override]
virtual #[cxx_virtual]
final #[cxx_final]
以下示例重写了从 QAbstractListModel 继承的 data 方法。

extern "RustQt" {
    #[qobject]
    #[base = "QAbstractListModel"]
    #[qml_element]
    #[qproperty(State, state)]
    type CustomBaseClass = super::CustomBaseClassRust;
}

unsafe extern "RustQt" {
    #[qinvokable]
    #[cxx_override]
    fn data(self: &CustomBaseClass, index: &QModelIndex, role: i32) -> QVariant;
}

impl qobject::CustomBaseClass {
    /// 检索给定索引和角色的数据
    pub fn data(&self, index: &QModelIndex, role: i32) -> QVariant {
        let role = qobject::Roles { repr: role };
        if let Some((id, value)) = self.vector.get(index.row() as usize) {
            return match role {
                qobject::Roles::Id => QVariant::from(id),
                qobject::Roles::Value => QVariant::from(value),
                _ => QVariant::default(),
            };
        }

        QVariant::default()
    }
}

完整示例

当使用 cxx_override 重写方法时,可以通过结合使用 #[inherit] 和 #[cxx_name] 属性来访问基类版本的方法。在这种情况下,基类版本的函数必须使用不同的名称,因为 Rust 不能在一个类型上拥有两个同名函数。

示例:

extern "RustQt" {
    #[qobject]
    #[base = "QAbstractListModel"]
    #[qml_element]
    #[qproperty(State, state)]
    type CustomBaseClass = super::CustomBaseClassRust;
}

unsafe extern "RustQt" {
    /// 从基类继承的 canFetchMore 方法
    #[cxx_name = "canFetchMore"]
    #[inherit]
    fn base_can_fetch_more(self: &CustomBaseClass, parent: &QModelIndex) -> bool;

    /// 从基类继承的 index 方法
    #[inherit]
    fn index(
        self: &CustomBaseClass,
        row: i32,
        column: i32,
        parent: &QModelIndex,
    ) -> QModelIndex;
}

unsafe extern "RustQt" {
    /// 返回基类是否可以获取更多数据
    // 示例:重写 C++ 虚方法并调用基类实现。
    #[qinvokable]
    #[cxx_override]
    #[cxx_name = "canFetchMore"]
    fn can_fetch_more(self: &CustomBaseClass, parent: &QModelIndex) -> bool;
}

impl qobject::CustomBaseClass {
    /// 返回基类是否可以获取更多数据
    // 示例:重写 C++ 虚方法并调用基类实现。
    pub fn can_fetch_more(&self, parent: &QModelIndex) -> bool {
        self.base_can_fetch_more(parent)
    }
}

相关文章:

  • 基于认证的 Harbor 容器镜像仓库
  • 基于koajsAdmin+mongodb的后台管理快速开发框架安装运行记录
  • 深度学习-151-Dify工具之创建一个生成财务报表的智能体Agent
  • 【容器运维】docker搭建私有仓库
  • 【MySQL篇】复合查询
  • 数学爱好者写的编程系列文章
  • Linux | make和Makefile命令详细篇
  • 深度学习:让机器学会“思考”的魔法
  • webpack使用详细步骤
  • SpringBootAdmin-clinet自定义监控CPU、内存、磁盘等health
  • Linux:xxx is not in the sudoers file. This incident will be reported.
  • macOS Sequoia 15.3 一直弹出“xx正在访问你的屏幕”
  • 深度学习篇---对角矩阵矩阵的秩奇异矩阵
  • 异地灾备介绍
  • STM32中断
  • 【Android】基于udp通信的智能家居移动应用开发
  • 强化学习中循环神经网络在序列决策中的应用研究
  • 每日一题-力扣-2680. 最大或值-20250321
  • 机器学习--DBSCAN聚类算法详解
  • [学习笔记] 部署Docker搭建靶场
  • 数理+AI+工程,上海交大将开首届“笛卡尔班”招生约20名
  • 江西暴雨强对流明显,专家:落雨区高度重叠,地质灾害风险高
  • “爱鸟周”为何不能像FI和花展那样“市区联动”
  • 国防部:正告菲方停止以任何方式冲撞中方核心利益
  • 圆桌丨权威专家解读中俄关系:在新形势下共同应对挑战、共创发展机遇
  • 普京:“胜利日停火”已开始生效