1. 程式人生 > >Qt C++屬性型別提供給 QML呼叫(三)

Qt C++屬性型別提供給 QML呼叫(三)

前言

前面兩篇文章已經介紹了 QML 中如何呼叫 C++中的基礎屬性以及物件屬性,今天繼續來介紹另外一種:物件為列表型別的屬性呼叫方法。

概述

包含QObject派生型別列表的屬性也可以暴露給QML使用,但是,應該使用QQmlListProperty類而不是QList< T >作為屬性型別。這是因為QList不是QObject派生的型別,所以不能通過Qt元物件系統提供必要的QML屬性特性,例如,當列表被修改時的訊號通知,這就需要呼叫物件為列表型別的屬性。

QQmlListProperty是一個模板類,可以通過QList值方便地構建。

正文

我們繼續在之前的工程中進行修改,新建一個 School 類,示例如下:

//school.h
#include <QQmlListProperty>
#include <QObject>
#include <QDebug>
#include "student.h"

class School : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QQmlListProperty<Student> students READ students)

public:

    explicit School(QObject * parent = 0);
    QQmlListProperty<Student> students();
    void
appendStudent(Student * stu); int studentCount() const; Student *student(int) const; void clearStudent(); private: static void appendStudent(QQmlListProperty<Student> *list, Student * s); static int studentCount(QQmlListProperty<Student>*); static Student* student(QQmlListProperty<Student>*, int
); static void clearStudent(QQmlListProperty<Student>*); private: QList<Student *> m_students; }; //school.cpp School::School(QObject *parent) : QObject(parent) { } QQmlListProperty<Student> School::students() { return QQmlListProperty<Student>(this,this, &School::appendStudent, &School::studentCount, &School::student, &School::clearStudent); } void School::appendStudent(Student *stu) { m_students.append(stu); } int School::studentCount() const { return m_students.count(); } Student *School::student(int index) const { return m_students.at(index); } void School::clearStudent() { return m_students.clear(); } void School::appendStudent(QQmlListProperty<Student> *list, Student *s) { reinterpret_cast< School* >(list->data)->appendStudent(s); } int School::studentCount(QQmlListProperty<Student> *list) { return reinterpret_cast< School* >(list->data)->studentCount(); } Student *School::student(QQmlListProperty<Student> *list, int i) { return reinterpret_cast< School* >(list->data)->student(i); } void School::clearStudent(QQmlListProperty<Student> *list) { reinterpret_cast< School* >(list->data)->clearStudent(); }

School 裡面提供了一個students列表,並註冊成QQmlListProperty型別供 QML 呼叫。

然後 Student 類保持不變:

class Student : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString name READ getName WRITE setName NOTIFY sigNameChanged)


public:
    explicit Student(QObject *parent = nullptr);
    ~Student(){}


    void setName(const QString & name){
        if(name != m_name){
            m_name = name;
            emit sigNameChanged(m_name);
        }
    }
    QString getName() const {return m_name;}
signals:
    void sigNameChanged(QString name);


private:
    QString m_name;

};

在 Main 函式中對類進行註冊:

qmlRegisterType<Student>("Student", 1, 0, "Student");
qmlRegisterType<School>("School", 1, 0, "School");

然後在 QML 中進行呼叫:

import QtQuick 2.8
import Student 1.0
import School 1.0

School{
    students:[
        Student{name:"xiaoming"},
        Student{name:"zhangsan"},
        Student{name:"lisi"}
    ]
}

這裡定義了一個School型別,其中包含三個 Student,每個 Student 設定其名稱。

然後我們回到 main 函式中 將 qml 定義好的物件打印出來看看效果:

QQmlEngine engine;
QQmlComponent component(&engine, QUrl("qrc:main.qml"));
School *school = qobject_cast<School *>(component.create());

if(school){
   for (int i = 0; i < school->studentCount(); ++i)
      qWarning() << "   " << school->student(i)->getName();
}

執行程式,輸出如下:

"xiaoming"
"zhangsan"
"lisi"

本文中是試驗從 QML 中建立列表物件,然後在C++中打印出建立好的列表,當然也可以在 C++中建立好列表,然後在 QML 中進行呼叫。使用方法都是一樣,這裡就不再贅述。

需要注意的是,在 Qt 幫助文件中,QQmlListProperty的使用方法如下:

class MessageBoard : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QQmlListProperty<Message> messages READ messages)
public:
    QQmlListProperty<Message> messages();

private:
    static void append_message(QQmlListProperty<Message> *list, Message *msg);

    QList<Message *> m_messages;
};

QQmlListProperty<Message> MessageBoard::messages()
{
    return QQmlListProperty<Message>(this, 0, &MessageBoard::append_message);
}

void MessageBoard::append_message(QQmlListProperty<Message> *list, Message *msg)
{
    MessageBoard *msgBoard = qobject_cast<MessageBoard *>(list->object);
    if (msg)
        msgBoard->m_messages.append(msg);
}
  • 這裡新增列表元素的時候只用到了一個靜態函式append_message,奇怪的是我用這種方法一直會報錯,編譯不通過,無奈之下用了第二種方法,將所有需要的靜態函式全部寫進去了。其實該類的建構函式有三個,如下:
QQmlListProperty::QQmlListProperty(QObject *object, QList<T *> &list)
QQmlListProperty::QQmlListProperty(QObject *object, void *data, AppendFunction append, CountFunction count, AtFunction at, ClearFunction clear)
QQmlListProperty::QQmlListProperty(QObject *object, void *data, CountFunction count, AtFunction at)

我用第一個建構函式的方式一直報錯,然而使用所有引數的形式就正常,目前還不知道是什麼原因,先這樣吧。

程式碼在這裡

相關推薦

Qt C++屬性型別供給 QML呼叫

前言 前面兩篇文章已經介紹了 QML 中如何呼叫 C++中的基礎屬性以及物件屬性,今天繼續來介紹另外一種:物件為列表型別的屬性呼叫方法。 概述 包含QObject派生型別列表的屬性也可以暴露給QML使用,但是,應該使用QQmlListProperty類

【黑馬程式設計師】Objective-C語言學習筆記之物件的建立、使用和方法呼叫

--------------------------------------------IOS期待與您交流!-------------------------------------------- 一、物件的建立 物件是由類建立,我們使用上一文章用到的類來建立物件。 說明:

C#多線程和異步——一些異步編程模式

img rar 效率 釋放 http 調用 完成 引用 iar 一、任務並行庫   任務並行庫(Task Parellel Library)是BCL中的一個類庫,極大地簡化了並行編程,這裏以Parallel.For和Parallel.ForEach為例。在C#中for/fo

effective C++筆記--模板與泛型程式設計

文章目錄 請使用traits classes表現型別資訊 認識模板超程式設計 請使用traits classes表現型別資訊 . traits並不是C++的關鍵字或是預先定義好的構件,它們是一種技術,也是一個C++程式設計師共同遵守的協議

Android NDK——必知必會之JNI的C++操作函式詳解和小結

引言 上一篇講解了一些關於JNI和NDK的必知必會的理論知識和機制,由於篇幅問題把關於JNI的重要的函式放到這篇,具體使用留到下一篇,此係列文章基連結: 一、JNI中的函式概述 在JNI層我們基本上都是通過env指標來呼叫jni.h標頭檔案裡定義的函式,JNI

C# 微信開發-----微信會員卡啟用會員卡

在會員領取了會員卡之後需要做 一個跳轉性啟用,模式請看下圖: 在建立會員卡的時候需要配置下這個引數的值:    memberActivate.aspx頁面程式碼如下: <%@ Page Language="C#" AutoEventWireup="tr

iOS下JS與OC互相呼叫--MessageHandler

使用WKWebView的時候,如果想要實現JS呼叫OC方法,除了攔截URL之外,還有一種簡單的方式。那就是利用WKWebView的新特性MessageHandler來實現JS呼叫原生方法。 MessageHandler 是什麼? WKWebView 初始

linux權輔助工具:privchecker.py

來自:https://www.securitysift.com/download/linuxprivchecker.py #!/usr/env python #######################################################################

C/C++:各種基本演算法實現小結—— 樹與二叉樹

各種基本演算法實現小結(三)—— 樹與二叉樹 (均已測試通過) =================================================================== 二叉樹——先序 測試環境:VC 6.0 (C

C++遞迴遍歷資料夾——建立樹結構

補充上篇部落格:遞迴遍歷資料夾時,同步在記憶體中建立相同的樹狀結構,用來描述所有檔案和資料夾的儲存結構。 具體實現如下: // recursion3.cpp #include <vect

C++生成dll供給C#和C++本身呼叫

1.專案整體結構如下:                                       &nb

C#可擴展編程之MEF學習筆記:導出類的方法和屬性

學習 說了 如何 mod ati dem ont num imp 前面說完了導入和導出的幾種方法,如果大家細心的話會註意到前面我們導出的都是類,那麽方法和屬性能不能導出呢???答案是肯定的,下面就來說下MEF是如何導出方法和屬性的。   還是前面的代碼,第二篇中已經提供了下

C++】Python呼叫C/C++互相呼叫

參考源: Python呼叫C/C++互相呼叫 C/C++與python互相呼叫 20181025 1.pytest.py #test function def add(a,b): print " in python function add"

C++ Primer Plus》學習筆記——第四章 複合型別

指標與自由儲存空間 指標是一個變數,其儲存的是值的地址,而不是值的本身。對於變數可以使用(&)地址運算子來獲取地址。 顯示地址時,常用的描述記憶體的表示法是十六進位制表示法。 對於常規變數,值是指定的量,而地址是派生量。 指標名錶示的是地址。*運算子被稱為間接值或解除引用運算

C++ 重點知識梳理 -------- 型別轉換、指標

dynamic_cast:該轉換符用於將一個指向派生類的基類指標或引用轉換為派生類的指標或引用。 const_cast:最常用的用途就是刪除const屬性。 static_cast:static_cast本質上是傳統c語言強制轉換的替代品,比C型別轉換更嚴格, 該操作符用於非多型型別的轉換,任何標準轉換都

C++深度解析 布林型別bool 和 引用 &3

C++深度解析 布林型別和引用(3)     1 布林型別 bool 在C++中,bool型別只有true(非0)和false(0)兩個值,且bool型別只佔用了一個位元組 true:非0 false:0  示例一: #include &

C#.網路程式設計 Socket基礎 基於WinForm系統Socket TCP協議 實現端到端伺服器與客戶端.txt.word.png等不同型別檔案傳輸

一、簡介: 前面的兩篇介紹了字串傳輸、圖片傳輸: 其實,本文針對Socket基礎(二)進一步完成,以便可以進行多種檔案傳輸。 二、基於不同的流(檔案流、記憶體流、網路等)讀寫。 1、圖片傳輸 方法一:(在客戶端用檔案流傳送(即將圖片寫到檔案流去,以便傳送),

VS2017的C++開發心得VS的常用專案屬性介紹

這一篇簡單介紹下常用的專案屬性的使用。 首先是配置管理器,在屬性頁的“配置管理器”按鍵開啟: 所有專案建立好了以後都有兩個預設的配置“Debug”和“Release”。 首先這個配置是什麼意思?屬性頁裡面有很多屬性,比如第一個常規分類下: 先看看圖裡標註的幾項

C#呼叫百度地圖API經驗分享

    這一篇我將跟大家分享一下我自己在開發過程中總結出的一些操作地圖的方法,屬性,及思路,希望可以讓大家少走彎路。 1.定位 一般百度的示例DEMO裡開始初始化地圖時用的都是map.centerAn

crf++模型訓練到c++、java呼叫介面

crf模型是個特別好用的模型,做分詞、做ner等nlp工作都力離不開,訓練crf模型用很多工具,比較出名的就是今天要講的crf++,其文件清晰,支援各種語言的介面,本篇blog要講的是c++和java的介面,   這裡java的介面是通過jni呼叫c++實際本質還是c++,不