QtQuick的Rust綁定 [qmetaobject]


第一步:
  安裝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(600) {
        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"), 10, cstr!("Greeter"));
    // 創建一個QML engine
    let mut engine=QmlEngine::new();
    engine.load_file("qrc:/qml/main.qml".into());
    engine.exec();
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM