QtQuick的Rust绑定 [qmetaobject]

参考 https://github.com/woboq/qmetaobject-rs 第一步:   安装qt,需要使用其中的qmake,将qmake路径放置环境变量中。   如果vscode或者idea中的终端不识别qmake但是在系统的powershell中可以,注意使用管理模式运行 第二步:创建rust项目
cargo new qt_rust_dome
第三步:在项目中创建build.rs
use semver::Version;
fn main() {
    eprintln!("cargo:warning={:?}", std::env::vars().collect::<Vec<_>>());
    let qt_include_path = std::env::var("DEP_QT_INCLUDE_PATH").unwrap();
    let qt_library_path = std::env::var("DEP_QT_LIBRARY_PATH").unwrap();
    let qt_version = std::env::var("DEP_QT_VERSION")
        .unwrap()
        .parse::<Version>()
        .expect("Parsing Qt version failed");
    let mut config = cpp_build::Config::new();
    if cfg!(target_os = "macos") {
        config.flag("-F");
        config.flag(&qt_library_path);
    }
    if qt_version >= Version::new(6, 0, 0) {
        config.flag_if_supported("-std=c++17");
        config.flag_if_supported("/std:c++17");
    }
    config.include(&qt_include_path).build("src/lib.rs");
    for minor in 7..=15 {
        if qt_version >= Version::new(5, minor, 0) {
            println!("cargo:rustc-cfg=qt_{}_{}", 5, minor);
        }
    }
    let mut minor = 0;
    while qt_version >= Version::new(6, minor, 0) {
        println!("cargo:rustc-cfg=qt_{}_{}", 6, minor);
        minor += 1;
    }
}
第四步:修改Cargo.toml
[package]
name = "qml_rust_dome"
version = "0.1.0"
edition = "2018"
build="build.rs"  // 注意这句话要添加上

[dependencies]
qmetaobject="*"  // qmetaobject
qttypes = { version = "0.2.2", features = [ "qtquick" ] }
cstr="0.2"
cpp = "0.5"
[build-dependencies]
cpp_build = "0.5" // 部分内容需要cpp编译?
semver="1.0.3"
第五步:创建qml文件
//main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
//这里引入模板
import Greeter 1.0
Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")
    //写一个qml的信号
    signal qml_Signal_btnTest_Clicked()
    Button {
        id: btnTest
        x: 251
        y: 187
        text: qsTr("btnTest")
        onClicked: {
            // 使用rust中的Greeter
            qobj.name="btnTest set the name"
            console.log("qml 调用Greeter中的add函数返回:",qobj.add(10,20)) // Greeter中的方法
            qml_Signal_btnTest_Clicked() //qml发送信号,Greeter接收
        }
    }
    //定义qml中的槽函数
    function slot_name_changed(){
        console.log('qml slot_name_changed 收到 onSignal_name_changed 的信号')
    }
    Greeter{
        id:qobj
        // 可以如此关联信号和槽,也可以在Component.onCompleted中关联
        // 如果同时关联,就同时执行
        onSignal_name_changed:{
            console.log('qml Greeter组件收到 onSignal_name_changed 信号')
        }
    }
    //组件加载完成后 关联信号和槽
    Component.onCompleted: {
        //Qml对象的信号关联到Greeter的槽函数
        qml_Signal_btnTest_Clicked.connect(qobj.slot_btnTest_Clicked)
        //把Greeter的信号关联到Qml
        qobj.onSignal_name_changed.connect(slot_name_changed)
    }
}

最后main.rs

//main.rs
extern crate qmetaobject;
use qmetaobject::*;
use cstr::cstr;
// 配置资源文件
// as前面的qml是文件目录,as后面的是虚拟路径
qrc!(my_resource,
    "qml" as "qml" {
        "main.qml",
    },
);
#[derive(QObject,Default)]
struct Greeter{
    //todo base是什么?
    base:qt_base_class!(trait QObject),
    // 定义一个属性,属性改变时发送 slot_name_changed 信号
    name:qt_property!(QString; NOTIFY signal_name_changed),
    // 定义一个信号
    signal_name_changed:qt_signal!(),
    // 定义一个槽
    slot_btnTest_Clicked:qt_method!(fn slot_btnTest_Clicked(&self){
        println!("--> slot_btnTest_Clicked:{}",self.name);
    }),
    // qml也可以直接调用
    add:qt_method!(fn add(&self,a:i32,b:i32)->i32{
        a+b
    }),
}
fn main() {
    // 注册资源文件
    my_resource();
    // 将Greeter注册到qml中 
    qml_register_type::<Greeter>(cstr!("Greeter"), 1, 0, cstr!("Greeter"));
    // 创建一个QML engine
    let mut engine=QmlEngine::new();
    engine.load_file("qrc:/qml/main.qml".into());
    engine.exec();
}

 

上一篇:我,35岁Android开发,高龄入职鹅厂,Android高级工程师面试实战


下一篇:员工工资表